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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [common/] [hw-tree.c] - Blame information for rev 450

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

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

powered by: WebSVN 2.1.0

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