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