OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [sim/] [common/] [hw-tree.c] - Blame information for rev 1775

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* The common simulator framework for GDB, the GNU Debugger.
2
 
3
   Copyright 2002 Free Software Foundation, Inc.
4
 
5
   Contributed by Andrew Cagney and Red Hat.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 2 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 59 Temple Place - Suite 330,
22
   Boston, MA 02111-1307, USA.  */
23
 
24
 
25
#include "hw-main.h"
26
#include "hw-base.h"
27
#include "hw-tree.h"
28
 
29
#include "sim-io.h"
30
#include "sim-assert.h"
31
 
32
#ifdef HAVE_STDLIB_H
33
#include <stdlib.h>
34
#endif
35
 
36
#ifdef HAVE_STRING_H
37
#include <string.h>
38
#else
39
#ifdef HAVE_STRINGS_H
40
#include <strings.h>
41
#endif
42
#endif
43
 
44
#include <ctype.h>
45
 
46
/* manipulate/lookup device names */
47
 
48
typedef struct _name_specifier {
49
 
50
  /* components in the full length name */
51
  char *path;
52
  char *property;
53
  char *value;
54
 
55
  /* current device */
56
  char *family;
57
  char *name;
58
  char *unit;
59
  char *args;
60
 
61
  /* previous device */
62
  char *last_name;
63
  char *last_family;
64
  char *last_unit;
65
  char *last_args;
66
 
67
  /* work area */
68
  char buf[1024];
69
 
70
} name_specifier;
71
 
72
 
73
 
74
/* Given a device specifier, break it up into its main components:
75
   path (and if present) property name and property value. */
76
 
77
static int
78
split_device_specifier (struct hw *current,
79
                        const char *device_specifier,
80
                        name_specifier *spec)
81
{
82
  char *chp = NULL;
83
 
84
  /* expand any leading alias if present */
85
  if (current != NULL
86
      && *device_specifier != '\0'
87
      && *device_specifier != '.'
88
      && *device_specifier != '/')
89
    {
90
      struct hw *aliases = hw_tree_find_device (current, "/aliases");
91
      char alias[32];
92
      int len = 0;
93
      while (device_specifier[len] != '\0'
94
             && device_specifier[len] != '/'
95
             && device_specifier[len] != ':'
96
             && !isspace (device_specifier[len]))
97
        {
98
          alias[len] = device_specifier[len];
99
          len++;
100
          if (len >= sizeof(alias))
101
            hw_abort (NULL, "split_device_specifier: buffer overflow");
102
        }
103
      alias[len] = '\0';
104
      if (aliases != NULL
105
          && hw_find_property (aliases, alias))
106
        {
107
          strcpy (spec->buf, hw_find_string_property(aliases, alias));
108
          strcat (spec->buf, device_specifier + len);
109
        }
110
      else
111
        {
112
          strcpy (spec->buf, device_specifier);
113
        }
114
    }
115
  else
116
    {
117
      strcpy(spec->buf, device_specifier);
118
    }
119
 
120
  /* check no overflow */
121
  if (strlen(spec->buf) >= sizeof(spec->buf))
122
    hw_abort (NULL, "split_device_specifier: buffer overflow\n");
123
 
124
  /* strip leading spaces */
125
  chp = spec->buf;
126
  while (*chp != '\0' && isspace(*chp))
127
    chp++;
128
  if (*chp == '\0')
129
    return 0;
130
 
131
  /* find the path and terminate it with null */
132
  spec->path = chp;
133
  while (*chp != '\0' && !isspace(*chp))
134
    chp++;
135
  if (*chp != '\0')
136
    {
137
      *chp = '\0';
138
      chp++;
139
    }
140
 
141
  /* and any value */
142
  while (*chp != '\0' && isspace(*chp))
143
    chp++;
144
  spec->value = chp;
145
 
146
  /* now go back and chop the property off of the path */
147
  if (spec->value[0] == '\0')
148
    {
149
      spec->property = NULL; /*not a property*/
150
      spec->value = NULL;
151
    }
152
  else if (spec->value[0] == '>'
153
           || spec->value[0] == '<')
154
    {
155
      /* an interrupt spec */
156
      spec->property = NULL;
157
    }
158
  else {
159
    chp = strrchr(spec->path, '/');
160
    if (chp == NULL)
161
      {
162
        spec->property = spec->path;
163
        spec->path = strchr(spec->property, '\0');
164
      }
165
    else {
166
      *chp = '\0';
167
      spec->property = chp+1;
168
    }
169
  }
170
 
171
  /* and mark the rest as invalid */
172
  spec->name = NULL;
173
  spec->family = NULL;
174
  spec->unit = NULL;
175
  spec->args = NULL;
176
  spec->last_name = NULL;
177
  spec->last_family = NULL;
178
  spec->last_unit = NULL;
179
  spec->last_args = NULL;
180
 
181
  return 1;
182
}
183
 
184
 
185
/* given a device specifier break it up into its main components -
186
   path and property name - assuming that the last `device' is a
187
   property name. */
188
 
189
static int
190
split_property_specifier (struct hw *current,
191
                          const char *property_specifier,
192
                          name_specifier *spec)
193
{
194
  if (split_device_specifier (current, property_specifier, spec))
195
    {
196
      if (spec->property == NULL)
197
        {
198
          /* force the last name to be a property name */
199
          char *chp = strrchr (spec->path, '/');
200
          if (chp == NULL)
201
            {
202
              spec->property = spec->path;
203
              spec->path = strrchr (spec->property, '\0');;
204
            }
205
          else
206
            {
207
              *chp = '\0';
208
              spec->property = chp + 1;
209
            }
210
        }
211
      return 1;
212
    }
213
  else
214
    return 0;
215
}
216
 
217
 
218
/* device the next device name and split it up, return 0 when no more
219
   names to struct hw */
220
 
221
static int
222
split_device_name (name_specifier *spec)
223
{
224
  char *chp;
225
  /* remember what came before */
226
  spec->last_name = spec->name;
227
  spec->last_family = spec->family;
228
  spec->last_unit = spec->unit;
229
  spec->last_args = spec->args;
230
  /* finished? */
231
  if (spec->path[0] == '\0')
232
    {
233
      spec->name = NULL;
234
      spec->family = NULL;
235
      spec->unit = NULL;
236
      spec->args = NULL;
237
      return 0;
238
    }
239
  /* break the current device spec from the path */
240
  spec->name = spec->path;
241
  chp = strchr (spec->name, '/');
242
  if (chp == NULL)
243
    spec->path = strchr (spec->name, '\0');
244
  else
245
    {
246
      spec->path = chp+1;
247
      *chp = '\0';
248
    }
249
  /* break out the base */
250
  if (spec->name[0] == '(')
251
    {
252
      chp = strchr(spec->name, ')');
253
      if (chp == NULL)
254
        {
255
          spec->family = spec->name;
256
        }
257
      else
258
        {
259
          *chp = '\0';
260
          spec->family = spec->name + 1;
261
          spec->name = chp + 1;
262
        }
263
    }
264
  else
265
    {
266
      spec->family = spec->name;
267
    }
268
  /* now break out the unit */
269
  chp = strchr(spec->name, '@');
270
  if (chp == NULL)
271
    {
272
      spec->unit = NULL;
273
      chp = spec->name;
274
    }
275
  else
276
    {
277
      *chp = '\0';
278
      chp += 1;
279
      spec->unit = chp;
280
    }
281
  /* finally any args */
282
  chp = strchr(chp, ':');
283
  if (chp == NULL)
284
    spec->args = NULL;
285
  else
286
    {
287
      *chp = '\0';
288
      spec->args = chp+1;
289
    }
290
  return 1;
291
}
292
 
293
 
294
/* device the value, returning the next non-space token */
295
 
296
static char *
297
split_value (name_specifier *spec)
298
{
299
  char *token;
300
  if (spec->value == NULL)
301
    return NULL;
302
  /* skip leading white space */
303
  while (isspace (spec->value[0]))
304
    spec->value++;
305
  if (spec->value[0] == '\0')
306
    {
307
      spec->value = NULL;
308
      return NULL;
309
    }
310
  token = spec->value;
311
  /* find trailing space */
312
  while (spec->value[0] != '\0' && !isspace (spec->value[0]))
313
    spec->value++;
314
  /* chop this value out */
315
  if (spec->value[0] != '\0')
316
    {
317
      spec->value[0] = '\0';
318
      spec->value++;
319
    }
320
  return token;
321
}
322
 
323
 
324
 
325
/* traverse the path specified by spec starting at current */
326
 
327
static struct hw *
328
split_find_device (struct hw *current,
329
                   name_specifier *spec)
330
{
331
  /* strip off (and process) any leading ., .., ./ and / */
332
  while (1)
333
    {
334
      if (strncmp (spec->path, "/", strlen ("/")) == 0)
335
        {
336
          /* cd /... */
337
          while (current != NULL && hw_parent (current) != NULL)
338
            current = hw_parent (current);
339
          spec->path += strlen ("/");
340
        }
341
      else if (strncmp (spec->path, "./", strlen ("./")) == 0)
342
        {
343
          /* cd ./... */
344
          current = current;
345
          spec->path += strlen ("./");
346
        }
347
      else if (strncmp (spec->path, "../", strlen ("../")) == 0)
348
        {
349
          /* cd ../... */
350
          if (current != NULL && hw_parent (current) != NULL)
351
            current = hw_parent (current);
352
          spec->path += strlen ("../");
353
        }
354
      else if (strcmp (spec->path, ".") == 0)
355
        {
356
          /* cd . */
357
          current = current;
358
          spec->path += strlen (".");
359
        }
360
      else if (strcmp (spec->path, "..") == 0)
361
        {
362
          /* cd .. */
363
          if (current != NULL && hw_parent (current) != NULL)
364
            current = hw_parent (current);
365
          spec->path += strlen ("..");
366
        }
367
      else
368
        break;
369
    }
370
 
371
  /* now go through the path proper */
372
 
373
  if (current == NULL)
374
    {
375
      split_device_name (spec);
376
      return NULL;
377
    }
378
 
379
  while (split_device_name (spec))
380
    {
381
      struct hw *child;
382
      for (child = hw_child (current);
383
           child != NULL; child = hw_sibling (child))
384
        {
385
          if (strcmp (spec->name, hw_name (child)) == 0)
386
            {
387
              if (spec->unit == NULL)
388
                break;
389
              else
390
                {
391
                  hw_unit phys;
392
                  hw_unit_decode (current, spec->unit, &phys);
393
                  if (memcmp (&phys, hw_unit_address (child),
394
                              sizeof (hw_unit)) == 0)
395
                    break;
396
                }
397
            }
398
        }
399
      if (child == NULL)
400
        return current; /* search failed */
401
      current = child;
402
    }
403
 
404
  return current;
405
}
406
 
407
 
408
static struct hw *
409
split_fill_path (struct hw *current,
410
                 const char *device_specifier,
411
                 name_specifier *spec)
412
{
413
  /* break it up */
414
  if (!split_device_specifier (current, device_specifier, spec))
415
    hw_abort (current, "error parsing %s\n", device_specifier);
416
 
417
  /* fill our tree with its contents */
418
  current = split_find_device (current, spec);
419
 
420
  /* add any additional devices as needed */
421
  if (spec->name != NULL)
422
    {
423
      do
424
        {
425
          if (current != NULL && !hw_finished_p (current))
426
            hw_finish (current);
427
          current = hw_create (NULL,
428
                               current,
429
                               spec->family,
430
                               spec->name,
431
                               spec->unit,
432
                               spec->args);
433
        }
434
      while (split_device_name (spec));
435
    }
436
 
437
  return current;
438
}
439
 
440
 
441
/* <non-white-space> */
442
 
443
static const char *
444
skip_token(const char *chp)
445
{
446
  while (!isspace(*chp) && *chp != '\0')
447
    chp++;
448
  while (isspace(*chp) && *chp != '\0')
449
    chp++;
450
  return chp;
451
}
452
 
453
 
454
/* count the number of entries */
455
 
456
static int
457
count_entries (struct hw *current,
458
               const char *property_name,
459
               const char *property_value,
460
               int modulo)
461
{
462
  const char *chp = property_value;
463
  int nr_entries = 0;
464
  while (*chp != '\0')
465
    {
466
      nr_entries += 1;
467
      chp = skip_token (chp);
468
    }
469
  if ((nr_entries % modulo) != 0)
470
    {
471
      hw_abort (current, "incorrect number of entries for %s property %s, should be multiple of %d",
472
                property_name, property_value, modulo);
473
    }
474
  return nr_entries / modulo;
475
}
476
 
477
 
478
 
479
/* parse: <address> ::= <token> ; device dependant */
480
 
481
static const char *
482
parse_address (struct hw *current,
483
               struct hw *bus,
484
               const char *chp,
485
               hw_unit *address)
486
{
487
  if (hw_unit_decode (bus, chp, address) < 0)
488
    hw_abort (current, "invalid unit address in %s", chp);
489
  return skip_token (chp);
490
}
491
 
492
 
493
/* parse: <size> ::= <number> { "," <number> } ; */
494
 
495
static const char *
496
parse_size (struct hw *current,
497
            struct hw *bus,
498
            const char *chp,
499
            hw_unit *size)
500
{
501
  int i;
502
  int nr;
503
  const char *curr = chp;
504
  memset(size, 0, sizeof(*size));
505
  /* parse the numeric list */
506
  size->nr_cells = hw_unit_nr_size_cells (bus);
507
  nr = 0;
508
  while (1)
509
    {
510
      char *next;
511
      size->cells[nr] = strtoul (curr, &next, 0);
512
      if (curr == next)
513
        hw_abort (current, "Problem parsing <size> %s", chp);
514
      nr += 1;
515
      if (next[0] != ',')
516
        break;
517
      if (nr == size->nr_cells)
518
        hw_abort (current, "Too many values in <size> %s", chp);
519
      curr = next + 1;
520
    }
521
  ASSERT (nr > 0 && nr <= size->nr_cells);
522
  /* right align the numbers */
523
  for (i = 1; i <= size->nr_cells; i++)
524
    {
525
      if (i <= nr)
526
        size->cells[size->nr_cells - i] = size->cells[nr - i];
527
      else
528
        size->cells[size->nr_cells - i] = 0;
529
    }
530
  return skip_token (chp);
531
}
532
 
533
 
534
/* parse: <reg> ::= { <address> <size> } ; */
535
 
536
static void
537
parse_reg_property (struct hw *current,
538
                    const char *property_name,
539
                    const char *property_value)
540
{
541
  int nr_regs;
542
  int reg_nr;
543
  reg_property_spec *regs;
544
  const char *chp;
545
 
546
  /* determine the number of reg entries by counting tokens */
547
  nr_regs = count_entries (current, property_name, property_value, 2);
548
 
549
  /* create working space */
550
  regs = zalloc (nr_regs * sizeof (*regs));
551
 
552
  /* fill it in */
553
  chp = property_value;
554
  for (reg_nr = 0; reg_nr < nr_regs; reg_nr++)
555
    {
556
      chp = parse_address (current, hw_parent(current),
557
                           chp, &regs[reg_nr].address);
558
      chp = parse_size (current, hw_parent(current),
559
                        chp, &regs[reg_nr].size);
560
    }
561
 
562
  /* create it */
563
  hw_add_reg_array_property (current, property_name,
564
                             regs, nr_regs);
565
 
566
  zfree (regs);
567
}
568
 
569
 
570
/* { <child-address> <parent-address> <child-size> }* */
571
 
572
static void
573
parse_ranges_property (struct hw *current,
574
                       const char *property_name,
575
                       const char *property_value)
576
{
577
  int nr_ranges;
578
  int range_nr;
579
  range_property_spec *ranges;
580
  const char *chp;
581
 
582
  /* determine the number of ranges specified */
583
  nr_ranges = count_entries (current, property_name, property_value, 3);
584
 
585
  /* create a property of that size */
586
  ranges = zalloc (nr_ranges * sizeof(*ranges));
587
 
588
  /* fill it in */
589
  chp = property_value;
590
  for (range_nr = 0; range_nr < nr_ranges; range_nr++)
591
    {
592
      chp = parse_address (current, current,
593
                           chp, &ranges[range_nr].child_address);
594
      chp = parse_address (current, hw_parent(current),
595
                           chp, &ranges[range_nr].parent_address);
596
      chp = parse_size (current, current,
597
                        chp, &ranges[range_nr].size);
598
    }
599
 
600
  /* create it */
601
  hw_add_range_array_property (current, property_name, ranges, nr_ranges);
602
 
603
  zfree (ranges);
604
}
605
 
606
 
607
/* <integer> ... */
608
 
609
static void
610
parse_integer_property (struct hw *current,
611
                        const char *property_name,
612
                        const char *property_value)
613
{
614
  int nr_entries;
615
  unsigned_cell words[1024];
616
  /* integer or integer array? */
617
  nr_entries = 0;
618
  while (1)
619
    {
620
      char *end;
621
      words[nr_entries] = strtoul (property_value, &end, 0);
622
      if (property_value == end)
623
        break;
624
      nr_entries += 1;
625
      if (nr_entries * sizeof (words[0]) >= sizeof (words))
626
        hw_abort (current, "buffer overflow");
627
      property_value = end;
628
    }
629
  if (nr_entries == 0)
630
    hw_abort (current, "error parsing integer property %s (%s)",
631
              property_name, property_value);
632
  else if (nr_entries == 1)
633
    hw_add_integer_property (current, property_name, words[0]);
634
  else
635
    {
636
      int i;
637
      for (i = 0; i < nr_entries; i++)
638
        {
639
          H2BE (words[i]);
640
        }
641
      /* perhaphs integer array property is better */
642
      hw_add_array_property (current, property_name, words,
643
                             sizeof(words[0]) * nr_entries);
644
    }
645
}
646
 
647
 
648
/* <string> ... */
649
 
650
static void
651
parse_string_property (struct hw *current,
652
                       const char *property_name,
653
                       const char *property_value)
654
{
655
  char **strings;
656
  const char *chp;
657
  int nr_strings;
658
  int approx_nr_strings;
659
 
660
  /* get an estimate as to the number of strings by counting double
661
     quotes */
662
  approx_nr_strings = 2;
663
  for (chp = property_value; *chp; chp++)
664
    {
665
      if (*chp == '"')
666
        approx_nr_strings++;
667
    }
668
  approx_nr_strings = (approx_nr_strings) / 2;
669
 
670
  /* create a string buffer for that many (plus a null) */
671
  strings = (char**) zalloc ((approx_nr_strings + 1) * sizeof(char*));
672
 
673
  /* now find all the strings */
674
  chp = property_value;
675
  nr_strings = 0;
676
  while (1)
677
    {
678
 
679
      /* skip leading space */
680
      while (*chp != '\0' && isspace (*chp))
681
        chp += 1;
682
      if (*chp == '\0')
683
        break;
684
 
685
      /* copy it in */
686
      if (*chp == '"')
687
        {
688
          /* a quoted string - watch for '\' et al. */
689
          /* estimate the size and allocate space for it */
690
          int pos;
691
          chp++;
692
          pos = 0;
693
          while (chp[pos] != '\0' && chp[pos] != '"')
694
            {
695
              if (chp[pos] == '\\' && chp[pos+1] != '\0')
696
                pos += 2;
697
              else
698
                pos += 1;
699
            }
700
          strings[nr_strings] = zalloc (pos + 1);
701
          /* copy the string over */
702
          pos = 0;
703
          while (*chp != '\0' && *chp != '"')
704
            {
705
              if (*chp == '\\' && *(chp+1) != '\0') {
706
                strings[nr_strings][pos] = *(chp+1);
707
                chp += 2;
708
                pos++;
709
              }
710
              else
711
                {
712
                  strings[nr_strings][pos] = *chp;
713
                  chp += 1;
714
                  pos++;
715
                }
716
            }
717
          if (*chp != '\0')
718
            chp++;
719
          strings[nr_strings][pos] = '\0';
720
        }
721
      else
722
        {
723
          /* copy over a single unquoted token */
724
          int len = 0;
725
          while (chp[len] != '\0' && !isspace(chp[len]))
726
            len++;
727
          strings[nr_strings] = zalloc(len + 1);
728
          strncpy(strings[nr_strings], chp, len);
729
          strings[nr_strings][len] = '\0';
730
          chp += len;
731
        }
732
      nr_strings++;
733
      if (nr_strings > approx_nr_strings)
734
        hw_abort (current, "String property %s badly formatted",
735
                  property_name);
736
    }
737
  ASSERT (strings[nr_strings] == NULL); /* from zalloc */
738
 
739
  /* install it */
740
  if (nr_strings == 0)
741
    hw_add_string_property (current, property_name, "");
742
  else if (nr_strings == 1)
743
    hw_add_string_property (current, property_name, strings[0]);
744
  else
745
    {
746
      const char **specs = (const char**) strings; /* stop a bogus error */
747
      hw_add_string_array_property (current, property_name,
748
                                    specs, nr_strings);
749
    }
750
 
751
  /* flush the created string */
752
  while (nr_strings > 0)
753
    {
754
      nr_strings--;
755
      zfree (strings[nr_strings]);
756
    }
757
  zfree(strings);
758
}
759
 
760
 
761
/* <path-to-ihandle-device> */
762
 
763
#if NOT_YET
764
static void
765
parse_ihandle_property (struct hw *current,
766
                        const char *property,
767
                        const char *value)
768
{
769
  ihandle_runtime_property_spec ihandle;
770
 
771
  /* pass the full path */
772
  ihandle.full_path = value;
773
 
774
  /* save this ready for the ihandle create */
775
  hw_add_ihandle_runtime_property (current, property,
776
                                   &ihandle);
777
}
778
#endif
779
 
780
 
781
struct hw *
782
hw_tree_create (SIM_DESC sd,
783
                const char *family)
784
{
785
  return hw_create (sd, NULL, family, family, NULL, NULL);
786
}
787
 
788
void
789
hw_tree_delete (struct hw *me)
790
{
791
  /* Need to allow devices to disapear under our feet */
792
  while (hw_child (me) != NULL)
793
    {
794
      hw_tree_delete (hw_child (me));
795
    }
796
  hw_delete (me);
797
}
798
 
799
 
800
struct hw *
801
hw_tree_parse (struct hw *current,
802
               const char *fmt,
803
               ...)
804
{
805
    va_list ap;
806
    va_start (ap, fmt);
807
    current = hw_tree_vparse (current, fmt, ap);
808
    va_end (ap);
809
    return current;
810
}
811
 
812
struct hw *
813
hw_tree_vparse (struct hw *current,
814
                const char *fmt,
815
                va_list ap)
816
{
817
  char device_specifier[1024];
818
  name_specifier spec;
819
 
820
  /* format the path */
821
  vsprintf (device_specifier, fmt, ap);
822
  if (strlen (device_specifier) >= sizeof (device_specifier))
823
    hw_abort (NULL, "device_tree_add_deviced: buffer overflow\n");
824
 
825
  /* construct the tree down to the final struct hw */
826
  current = split_fill_path (current, device_specifier, &spec);
827
 
828
  /* is there an interrupt spec */
829
  if (spec.property == NULL
830
      && spec.value != NULL)
831
    {
832
      char *op = split_value (&spec);
833
      switch (op[0])
834
        {
835
        case '>':
836
          {
837
            char *my_port_name = split_value (&spec);
838
            int my_port;
839
            char *dest_port_name = split_value (&spec);
840
            int dest_port;
841
            name_specifier dest_spec;
842
            char *dest_hw_name = split_value (&spec);
843
            struct hw *dest;
844
            /* find my name */
845
            if (!hw_finished_p (current))
846
              hw_finish (current);
847
            my_port = hw_port_decode (current, my_port_name, output_port);
848
            /* find the dest device and port */
849
            dest = split_fill_path (current, dest_hw_name, &dest_spec);
850
            if (!hw_finished_p (dest))
851
              hw_finish (dest);
852
            dest_port = hw_port_decode (dest, dest_port_name,
853
                                        input_port);
854
            /* connect the two */
855
            hw_port_attach (current,
856
                            my_port,
857
                            dest,
858
                            dest_port,
859
                            permenant_object);
860
            break;
861
          }
862
        default:
863
          hw_abort (current, "unreconised interrupt spec %s\n", spec.value);
864
          break;
865
        }
866
    }
867
 
868
  /* is there a property */
869
  if (spec.property != NULL)
870
    {
871
      if (strcmp (spec.value, "true") == 0)
872
        hw_add_boolean_property (current, spec.property, 1);
873
      else if (strcmp (spec.value, "false") == 0)
874
        hw_add_boolean_property (current, spec.property, 0);
875
      else
876
        {
877
          const struct hw_property *property;
878
          switch (spec.value[0])
879
            {
880
#if NOT_YET
881
            case '*':
882
              {
883
                parse_ihandle_property (current, spec.property, spec.value + 1);
884
                break;
885
              }
886
#endif
887
            case '[':
888
              {
889
                unsigned8 words[1024];
890
                char *curr = spec.value + 1;
891
                int nr_words = 0;
892
                while (1)
893
                  {
894
                    char *next;
895
                    words[nr_words] = H2BE_1 (strtoul (curr, &next, 0));
896
                    if (curr == next)
897
                      break;
898
                    curr = next;
899
                    nr_words += 1;
900
                  }
901
                hw_add_array_property (current, spec.property,
902
                                       words, sizeof(words[0]) * nr_words);
903
                break;
904
              }
905
            case '"':
906
              {
907
                parse_string_property (current, spec.property, spec.value);
908
                break;
909
              }
910
            case '!':
911
              {
912
                spec.value++;
913
                property = hw_tree_find_property (current, spec.value);
914
                if (property == NULL)
915
                  hw_abort (current, "property %s not found\n", spec.value);
916
                hw_add_duplicate_property (current,
917
                                           spec.property,
918
                                           property);
919
                break;
920
              }
921
            default:
922
              {
923
                if (strcmp (spec.property, "reg") == 0
924
                    || strcmp (spec.property, "assigned-addresses") == 0
925
                    || strcmp (spec.property, "alternate-reg") == 0)
926
                  {
927
                    parse_reg_property (current, spec.property, spec.value);
928
                  }
929
                else if (strcmp (spec.property, "ranges") == 0)
930
                  {
931
                    parse_ranges_property (current, spec.property, spec.value);
932
                  }
933
                else if (isdigit(spec.value[0])
934
                         || (spec.value[0] == '-' && isdigit(spec.value[1]))
935
                         || (spec.value[0] == '+' && isdigit(spec.value[1])))
936
                  {
937
                    parse_integer_property(current, spec.property, spec.value);
938
                  }
939
                else
940
                  parse_string_property(current, spec.property, spec.value);
941
                break;
942
              }
943
            }
944
        }
945
    }
946
  return current;
947
}
948
 
949
 
950
static void
951
finish_hw_tree (struct hw *me,
952
                void *data)
953
{
954
  if (!hw_finished_p (me))
955
    hw_finish (me);
956
}
957
 
958
void
959
hw_tree_finish (struct hw *root)
960
{
961
  hw_tree_traverse (root, finish_hw_tree, NULL, NULL);
962
}
963
 
964
 
965
 
966
void
967
hw_tree_traverse (struct hw *root,
968
                  hw_tree_traverse_function *prefix,
969
                  hw_tree_traverse_function *postfix,
970
                  void *data)
971
{
972
  struct hw *child;
973
  if (prefix != NULL)
974
    prefix (root, data);
975
  for (child = hw_child (root);
976
       child != NULL;
977
       child = hw_sibling (child))
978
    {
979
      hw_tree_traverse (child, prefix, postfix, data);
980
    }
981
  if (postfix != NULL)
982
    postfix (root, data);
983
}
984
 
985
 
986
 
987
struct printer {
988
  hw_tree_print_callback *print;
989
  void *file;
990
};
991
 
992
static void
993
print_address (struct hw *bus,
994
               const hw_unit *phys,
995
               struct printer *p)
996
{
997
  char unit[32];
998
  hw_unit_encode (bus, phys, unit, sizeof(unit));
999
  p->print (p->file, " %s", unit);
1000
}
1001
 
1002
static void
1003
print_size (struct hw *bus,
1004
            const hw_unit *size,
1005
            struct printer *p)
1006
{
1007
  int i;
1008
  for (i = 0; i < size->nr_cells; i++)
1009
    if (size->cells[i] != 0)
1010
      break;
1011
  if (i < size->nr_cells) {
1012
    p->print (p->file, " 0x%lx", (unsigned long) size->cells[i]);
1013
    i++;
1014
    for (; i < size->nr_cells; i++)
1015
      p->print (p->file, ",0x%lx", (unsigned long) size->cells[i]);
1016
  }
1017
  else
1018
    p->print (p->file, " 0");
1019
}
1020
 
1021
static void
1022
print_reg_property (struct hw *me,
1023
                    const struct hw_property *property,
1024
                    struct printer *p)
1025
{
1026
  int reg_nr;
1027
  reg_property_spec reg;
1028
  for (reg_nr = 0;
1029
       hw_find_reg_array_property (me, property->name, reg_nr, &reg);
1030
       reg_nr++) {
1031
    print_address (hw_parent (me), &reg.address, p);
1032
    print_size (me, &reg.size, p);
1033
  }
1034
}
1035
 
1036
static void
1037
print_ranges_property (struct hw *me,
1038
                       const struct hw_property *property,
1039
                       struct printer *p)
1040
{
1041
  int range_nr;
1042
  range_property_spec range;
1043
  for (range_nr = 0;
1044
       hw_find_range_array_property (me, property->name, range_nr, &range);
1045
       range_nr++)
1046
    {
1047
      print_address (me, &range.child_address, p);
1048
      print_address (hw_parent (me), &range.parent_address, p);
1049
      print_size (me, &range.size, p);
1050
    }
1051
}
1052
 
1053
static void
1054
print_string (struct hw *me,
1055
              const char *string,
1056
              struct printer *p)
1057
{
1058
  p->print (p->file, " \"");
1059
  while (*string != '\0') {
1060
    switch (*string) {
1061
    case '"':
1062
      p->print (p->file, "\\\"");
1063
      break;
1064
    case '\\':
1065
      p->print (p->file, "\\\\");
1066
      break;
1067
    default:
1068
      p->print (p->file, "%c", *string);
1069
      break;
1070
    }
1071
    string++;
1072
  }
1073
  p->print (p->file, "\"");
1074
}
1075
 
1076
static void
1077
print_string_array_property (struct hw *me,
1078
                             const struct hw_property *property,
1079
                             struct printer *p)
1080
{
1081
  int nr;
1082
  string_property_spec string;
1083
  for (nr = 0;
1084
       hw_find_string_array_property (me, property->name, nr, &string);
1085
       nr++)
1086
    {
1087
      print_string (me, string, p);
1088
    }
1089
}
1090
 
1091
static void
1092
print_properties (struct hw *me,
1093
                  struct printer *p)
1094
{
1095
  const struct hw_property *property;
1096
  for (property = hw_find_property (me, NULL);
1097
       property != NULL;
1098
       property = hw_next_property (property))
1099
    {
1100
      if (hw_parent (me) == NULL)
1101
        p->print (p->file, "/%s", property->name);
1102
      else
1103
        p->print (p->file, "%s/%s", hw_path (me), property->name);
1104
      if (property->original != NULL)
1105
        {
1106
          p->print (p->file, " !");
1107
          p->print (p->file, "%s/%s",
1108
                     hw_path (property->original->owner),
1109
                     property->original->name);
1110
        }
1111
      else
1112
        {
1113
          switch (property->type)
1114
            {
1115
            case array_property:
1116
              {
1117
                if ((property->sizeof_array % sizeof (signed_cell)) == 0)
1118
                  {
1119
                    unsigned_cell *w = (unsigned_cell*) property->array;
1120
                    int cell_nr;
1121
                    for (cell_nr = 0;
1122
                         cell_nr < (property->sizeof_array / sizeof (unsigned_cell));
1123
                         cell_nr++)
1124
                      {
1125
                        p->print (p->file, " 0x%lx", (unsigned long) BE2H_cell (w[cell_nr]));
1126
                      }
1127
                  }
1128
                else
1129
                  {
1130
                    unsigned8 *w = (unsigned8*)property->array;
1131
                    p->print (p->file, " [");
1132
                    while ((char*)w - (char*)property->array < property->sizeof_array) {
1133
                      p->print (p->file, " 0x%2x", BE2H_1 (*w));
1134
                      w++;
1135
                    }
1136
                  }
1137
                break;
1138
              }
1139
            case boolean_property:
1140
              {
1141
                int b = hw_find_boolean_property(me, property->name);
1142
                p->print (p->file, " %s", b ? "true"  : "false");
1143
                break;
1144
              }
1145
#if NOT_YET
1146
            case ihandle_property:
1147
              {
1148
                if (property->array != NULL)
1149
                  {
1150
                    device_instance *instance = hw_find_ihandle_property (me, property->name);
1151
                    p->print (p->file, " *%s", device_instance_path(instance));
1152
                  }
1153
                else
1154
                  {
1155
                    /* not yet initialized, ask the device for the path */
1156
                    ihandle_runtime_property_spec spec;
1157
                    hw_find_ihandle_runtime_property (me, property->name, &spec);
1158
                    p->print (p->file, " *%s", spec.full_path);
1159
                  }
1160
                break;
1161
              }
1162
#endif
1163
            case integer_property:
1164
              {
1165
                unsigned_word w = hw_find_integer_property (me, property->name);
1166
                p->print (p->file, " 0x%lx", (unsigned long)w);
1167
                break;
1168
              }
1169
            case range_array_property:
1170
              {
1171
                print_ranges_property (me, property, p);
1172
                break;
1173
              }
1174
            case reg_array_property:
1175
              {
1176
                print_reg_property (me, property, p);
1177
                break;
1178
              }
1179
            case string_property:
1180
              {
1181
                const char *s = hw_find_string_property (me, property->name);
1182
                print_string (me, s, p);
1183
                break;
1184
              }
1185
            case string_array_property:
1186
              {
1187
                print_string_array_property (me, property, p);
1188
                break;
1189
              }
1190
            }
1191
        }
1192
      p->print (p->file, "\n");
1193
    }
1194
}
1195
 
1196
static void
1197
print_interrupts (struct hw *me,
1198
                  int my_port,
1199
                  struct hw *dest,
1200
                  int dest_port,
1201
                  void *data)
1202
{
1203
  struct printer *p = data;
1204
  char src[32];
1205
  char dst[32];
1206
  hw_port_encode (me, my_port, src, sizeof(src), output_port);
1207
  hw_port_encode (dest, dest_port, dst, sizeof(dst), input_port);
1208
  p->print (p->file,
1209
            "%s > %s %s %s\n",
1210
            hw_path (me),
1211
            src, dst,
1212
            hw_path (dest));
1213
}
1214
 
1215
static void
1216
print_device (struct hw *me,
1217
              void *data)
1218
{
1219
  struct printer *p = data;
1220
  p->print (p->file, "%s\n", hw_path (me));
1221
  print_properties (me, p);
1222
  hw_port_traverse (me, print_interrupts, data);
1223
}
1224
 
1225
void
1226
hw_tree_print (struct hw *root,
1227
               hw_tree_print_callback *print,
1228
               void *file)
1229
{
1230
  struct printer p;
1231
  p.print = print;
1232
  p.file = file;
1233
  hw_tree_traverse (root,
1234
                    print_device, NULL,
1235
                    &p);
1236
}
1237
 
1238
 
1239
 
1240
#if NOT_YET
1241
device_instance *
1242
tree_instance(struct hw *root,
1243
              const char *device_specifier)
1244
{
1245
  /* find the device node */
1246
  struct hw *me;
1247
  name_specifier spec;
1248
  if (!split_device_specifier(root, device_specifier, &spec))
1249
    return NULL;
1250
  me = split_find_device(root, &spec);
1251
  if (spec.name != NULL)
1252
    return NULL;
1253
  /* create the instance */
1254
  return device_create_instance(me, device_specifier, spec.last_args);
1255
}
1256
#endif
1257
 
1258
struct hw *
1259
hw_tree_find_device (struct hw *root,
1260
                     const char *path_to_device)
1261
{
1262
  struct hw *node;
1263
  name_specifier spec;
1264
 
1265
  /* parse the path */
1266
  split_device_specifier (root, path_to_device, &spec);
1267
  if (spec.value != NULL)
1268
    return NULL; /* something wierd */
1269
 
1270
  /* now find it */
1271
  node = split_find_device (root, &spec);
1272
  if (spec.name != NULL)
1273
    return NULL; /* not a leaf */
1274
 
1275
  return node;
1276
}
1277
 
1278
 
1279
const struct hw_property *
1280
hw_tree_find_property (struct hw *root,
1281
                       const char *path_to_property)
1282
{
1283
  name_specifier spec;
1284
  if (!split_property_specifier (root, path_to_property, &spec))
1285
    hw_abort (root, "Invalid property path %s", path_to_property);
1286
  root = split_find_device (root, &spec);
1287
  if (spec.name != NULL)
1288
    return NULL; /* not a leaf */
1289
  return hw_find_property (root, spec.property);
1290
}
1291
 
1292
int
1293
hw_tree_find_boolean_property (struct hw *root,
1294
                               const char *path_to_property)
1295
{
1296
  name_specifier spec;
1297
  if (!split_property_specifier (root, path_to_property, &spec))
1298
    hw_abort (root, "Invalid property path %s", path_to_property);
1299
  root = split_find_device (root, &spec);
1300
  if (spec.name != NULL)
1301
    hw_abort (root, "device \"%s\" not found (property \"%s\")",
1302
              spec.name, path_to_property);
1303
  return hw_find_boolean_property (root, spec.property);
1304
}
1305
 
1306
signed_cell
1307
hw_tree_find_integer_property (struct hw *root,
1308
                               const char *path_to_property)
1309
{
1310
  name_specifier spec;
1311
  if (!split_property_specifier (root, path_to_property, &spec))
1312
    hw_abort (root, "Invalid property path %s", path_to_property);
1313
  root = split_find_device (root, &spec);
1314
  if (spec.name != NULL)
1315
    hw_abort (root, "device \"%s\" not found (property \"%s\")",
1316
              spec.name, path_to_property);
1317
  return hw_find_integer_property (root, spec.property);
1318
}
1319
 
1320
#if NOT_YET
1321
device_instance *
1322
hw_tree_find_ihandle_property (struct hw *root,
1323
                               const char *path_to_property)
1324
{
1325
  struct hw *root;
1326
  name_specifier spec;
1327
  if (!split_property_specifier (root, path_to_property, &spec))
1328
    hw_abort (root, "Invalid property path %s", path_to_property);
1329
  root = split_find_device (root, &spec);
1330
  if (spec.name != NULL)
1331
    hw_abort (root, "device \"%s\" not found (property \"%s\")",
1332
              spec.name, path_to_property);
1333
  return hw_find_ihandle_property (root, spec.property);
1334
}
1335
#endif
1336
 
1337
const char *
1338
hw_tree_find_string_property (struct hw *root,
1339
                              const char *path_to_property)
1340
{
1341
  name_specifier spec;
1342
  if (!split_property_specifier (root, path_to_property, &spec))
1343
    hw_abort (root, "Invalid property path %s", path_to_property);
1344
  root = split_find_device (root, &spec);
1345
  if (spec.name != NULL)
1346
    hw_abort (root, "device \"%s\" not found (property \"%s\")",
1347
              spec.name, path_to_property);
1348
  return hw_find_string_property (root, spec.property);
1349
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.