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 <string.h>
     26  1.10  christos 
     27   1.1  christos #include "hw-main.h"
     28   1.1  christos #include "hw-base.h"
     29   1.1  christos 
     30   1.1  christos #include "sim-io.h"
     31   1.1  christos #include "sim-assert.h"
     32   1.1  christos 
     33   1.1  christos /* property entries */
     34   1.1  christos 
     35   1.1  christos struct hw_property_data
     36   1.1  christos {
     37   1.1  christos   struct hw_property_data *next;
     38   1.1  christos   struct hw_property *property;
     39   1.1  christos   const void *init_array;
     40   1.1  christos   unsigned sizeof_init_array;
     41   1.1  christos };
     42   1.1  christos 
     43   1.1  christos void
     44   1.1  christos create_hw_property_data (struct hw *me)
     45   1.1  christos {
     46   1.1  christos }
     47   1.1  christos 
     48   1.1  christos void
     49   1.1  christos delete_hw_property_data (struct hw *me)
     50   1.1  christos {
     51   1.1  christos }
     52   1.1  christos 
     53   1.1  christos 
     54   1.1  christos /* Device Properties: */
     55   1.1  christos 
     56   1.1  christos static struct hw_property_data *
     57   1.1  christos find_property_data (struct hw *me,
     58   1.1  christos 		    const char *property)
     59   1.1  christos {
     60   1.1  christos   struct hw_property_data *entry;
     61   1.1  christos   ASSERT (property != NULL);
     62   1.1  christos   entry = me->properties_of_hw;
     63   1.1  christos   while (entry != NULL)
     64   1.1  christos     {
     65   1.1  christos       if (strcmp (entry->property->name, property) == 0)
     66   1.1  christos 	return entry;
     67   1.1  christos       entry = entry->next;
     68   1.1  christos     }
     69   1.1  christos   return NULL;
     70   1.1  christos }
     71   1.1  christos 
     72   1.1  christos 
     73   1.1  christos static void
     74   1.1  christos hw_add_property (struct hw *me,
     75   1.1  christos 		 const char *property,
     76   1.1  christos 		 hw_property_type type,
     77   1.1  christos 		 const void *init_array,
     78   1.1  christos 		 unsigned sizeof_init_array,
     79   1.1  christos 		 const void *array,
     80   1.1  christos 		 unsigned sizeof_array,
     81   1.1  christos 		 const struct hw_property *original,
     82   1.1  christos 		 object_disposition disposition)
     83   1.1  christos {
     84   1.1  christos   struct hw_property_data *new_entry = NULL;
     85   1.1  christos   struct hw_property *new_value = NULL;
     86   1.1  christos 
     87   1.1  christos   /* find the list end */
     88   1.1  christos   struct hw_property_data **insertion_point = &me->properties_of_hw;
     89   1.1  christos   while (*insertion_point != NULL)
     90   1.1  christos     {
     91   1.1  christos       if (strcmp ((*insertion_point)->property->name, property) == 0)
     92   1.1  christos 	return;
     93   1.1  christos       insertion_point = &(*insertion_point)->next;
     94   1.1  christos     }
     95   1.1  christos 
     96   1.1  christos   /* create a new value */
     97   1.1  christos   new_value = HW_ZALLOC (me, struct hw_property);
     98   1.1  christos   new_value->name = (char *) strdup (property);
     99   1.1  christos   new_value->type = type;
    100   1.1  christos   if (sizeof_array > 0)
    101   1.1  christos     {
    102   1.1  christos       void *new_array = hw_zalloc (me, sizeof_array);
    103   1.1  christos       memcpy (new_array, array, sizeof_array);
    104   1.1  christos       new_value->array = new_array;
    105   1.1  christos       new_value->sizeof_array = sizeof_array;
    106   1.1  christos     }
    107   1.1  christos   new_value->owner = me;
    108   1.1  christos   new_value->original = original;
    109   1.1  christos   new_value->disposition = disposition;
    110   1.1  christos 
    111   1.1  christos   /* insert the value into the list */
    112   1.1  christos   new_entry = HW_ZALLOC (me, struct hw_property_data);
    113   1.1  christos   *insertion_point = new_entry;
    114   1.1  christos   if (sizeof_init_array > 0)
    115   1.1  christos     {
    116   1.1  christos       void *new_init_array = hw_zalloc (me, sizeof_init_array);
    117   1.1  christos       memcpy (new_init_array, init_array, sizeof_init_array);
    118   1.1  christos       new_entry->init_array = new_init_array;
    119   1.1  christos       new_entry->sizeof_init_array = sizeof_init_array;
    120   1.1  christos     }
    121   1.1  christos   new_entry->property = new_value;
    122   1.1  christos }
    123   1.1  christos 
    124   1.1  christos 
    125   1.1  christos static void
    126   1.1  christos hw_set_property (struct hw *me,
    127   1.1  christos 		 const char *property,
    128   1.1  christos 		 hw_property_type type,
    129   1.1  christos 		 const void *array,
    130   1.1  christos 		 int sizeof_array)
    131   1.1  christos {
    132   1.1  christos   /* find the property */
    133   1.1  christos   struct hw_property_data *entry = find_property_data (me, property);
    134   1.1  christos   if (entry != NULL)
    135   1.1  christos     {
    136   1.1  christos       /* existing property - update it */
    137   1.1  christos       void *new_array = 0;
    138   1.1  christos       struct hw_property *value = entry->property;
    139   1.1  christos       /* check the type matches */
    140   1.1  christos       if (value->type != type)
    141   1.1  christos 	hw_abort (me, "conflict between type of new and old value for property %s", property);
    142   1.1  christos       /* replace its value */
    143   1.1  christos       if (value->array != NULL)
    144   1.1  christos 	hw_free (me, (void*)value->array);
    145   1.1  christos       new_array = (sizeof_array > 0
    146   1.1  christos 		   ? hw_zalloc (me, sizeof_array)
    147   1.1  christos 		   : (void*)0);
    148   1.1  christos       value->array = new_array;
    149   1.1  christos       value->sizeof_array = sizeof_array;
    150   1.1  christos       if (sizeof_array > 0)
    151   1.1  christos 	memcpy (new_array, array, sizeof_array);
    152   1.1  christos       return;
    153   1.1  christos     }
    154   1.1  christos   else
    155   1.1  christos     {
    156   1.1  christos       /* new property - create it */
    157   1.1  christos       hw_add_property (me, property, type,
    158   1.1  christos 		       NULL, 0, array, sizeof_array,
    159   1.1  christos 		       NULL, temporary_object);
    160   1.1  christos     }
    161   1.1  christos }
    162   1.1  christos 
    163   1.1  christos 
    164   1.1  christos #if 0
    165   1.1  christos static void
    166   1.1  christos clean_hw_properties (struct hw *me)
    167   1.1  christos {
    168   1.1  christos   struct hw_property_data **delete_point = &me->properties_of_hw;
    169   1.1  christos   while (*delete_point != NULL)
    170   1.1  christos     {
    171   1.1  christos       struct hw_property_data *current = *delete_point;
    172   1.1  christos       switch (current->property->disposition)
    173   1.1  christos 	{
    174  1.11  christos 	case permanent_object:
    175   1.1  christos 	  /* zap the current value, will be initialized later */
    176   1.1  christos 	  ASSERT (current->init_array != NULL);
    177   1.1  christos 	  if (current->property->array != NULL)
    178   1.1  christos 	    {
    179   1.1  christos 	      hw_free (me, (void*)current->property->array);
    180   1.1  christos 	      current->property->array = NULL;
    181   1.1  christos 	    }
    182   1.1  christos 	  delete_point = &(*delete_point)->next;
    183   1.1  christos 	  break;
    184   1.1  christos 	case temporary_object:
    185   1.1  christos 	  /* zap the actual property, was created during simulation run */
    186   1.1  christos 	  ASSERT (current->init_array == NULL);
    187   1.1  christos 	  *delete_point = current->next;
    188   1.1  christos 	  if (current->property->array != NULL)
    189   1.1  christos 	    hw_free (me, (void*)current->property->array);
    190   1.1  christos 	  hw_free (me, current->property);
    191   1.1  christos 	  hw_free (me, current);
    192   1.1  christos 	  break;
    193   1.1  christos 	}
    194   1.1  christos     }
    195   1.1  christos }
    196   1.1  christos #endif
    197   1.1  christos 
    198   1.1  christos #if 0
    199   1.1  christos void
    200   1.1  christos hw_init_static_properties (SIM_DESC sd,
    201   1.1  christos 			   struct hw *me,
    202   1.1  christos 			   void *data)
    203   1.1  christos {
    204   1.1  christos   struct hw_property_data *property;
    205   1.1  christos   for (property = me->properties_of_hw;
    206   1.1  christos        property != NULL;
    207   1.1  christos        property = property->next)
    208   1.1  christos     {
    209   1.1  christos       ASSERT (property->init_array != NULL);
    210   1.1  christos       ASSERT (property->property->array == NULL);
    211  1.11  christos       ASSERT (property->property->disposition == permanent_object);
    212   1.1  christos       switch (property->property->type)
    213   1.1  christos 	{
    214   1.1  christos 	case array_property:
    215   1.1  christos 	case boolean_property:
    216   1.1  christos 	case range_array_property:
    217   1.1  christos 	case reg_array_property:
    218   1.1  christos 	case string_property:
    219   1.1  christos 	case string_array_property:
    220   1.1  christos 	case integer_property:
    221   1.1  christos 	  /* delete the property, and replace it with the original */
    222   1.1  christos 	  hw_set_property (me, property->property->name,
    223   1.1  christos 			   property->property->type,
    224   1.1  christos 			   property->init_array,
    225   1.1  christos 			   property->sizeof_init_array);
    226   1.1  christos 	  break;
    227   1.1  christos #if 0
    228   1.1  christos 	case ihandle_property:
    229   1.1  christos 	  break;
    230   1.1  christos #endif
    231   1.1  christos 	}
    232   1.1  christos     }
    233   1.1  christos }
    234   1.1  christos #endif
    235   1.1  christos 
    236   1.1  christos 
    237   1.1  christos #if 0
    238   1.1  christos void
    239   1.1  christos hw_init_runtime_properties (SIM_DESC sd,
    240   1.1  christos 			    struct hw *me,
    241   1.1  christos 			    void *data)
    242   1.1  christos {
    243   1.1  christos   struct hw_property_data *property;
    244   1.1  christos   for (property = me->properties_of_hw;
    245   1.1  christos        property != NULL;
    246   1.1  christos        property = property->next)
    247   1.1  christos     {
    248   1.1  christos       switch (property->property->disposition)
    249   1.1  christos 	{
    250  1.11  christos 	case permanent_object:
    251   1.1  christos 	  switch (property->property->type)
    252   1.1  christos 	    {
    253   1.1  christos #if 0
    254   1.1  christos 	    case ihandle_property:
    255   1.1  christos 	      {
    256   1.1  christos 		struct hw_instance *ihandle;
    257   1.1  christos 		ihandle_runtime_property_spec spec;
    258   1.1  christos 		ASSERT (property->init_array != NULL);
    259   1.1  christos 		ASSERT (property->property->array == NULL);
    260   1.1  christos 		hw_find_ihandle_runtime_property (me, property->property->name, &spec);
    261   1.1  christos 		ihandle = tree_instance (me, spec.full_path);
    262   1.1  christos 		hw_set_ihandle_property (me, property->property->name, ihandle);
    263   1.1  christos 		break;
    264   1.1  christos 	      }
    265   1.1  christos #endif
    266   1.1  christos 	    case array_property:
    267   1.1  christos 	    case boolean_property:
    268   1.1  christos 	    case range_array_property:
    269   1.1  christos 	    case integer_property:
    270   1.1  christos 	    case reg_array_property:
    271   1.1  christos 	    case string_property:
    272   1.1  christos 	    case string_array_property:
    273   1.1  christos 	      ASSERT (property->init_array != NULL);
    274   1.1  christos 	      ASSERT (property->property->array != NULL);
    275   1.1  christos 	      break;
    276   1.1  christos 	    }
    277   1.1  christos 	  break;
    278   1.1  christos 	case temporary_object:
    279   1.1  christos 	  ASSERT (property->init_array == NULL);
    280   1.1  christos 	  ASSERT (property->property->array != NULL);
    281   1.1  christos 	  break;
    282   1.1  christos 	}
    283   1.1  christos     }
    284   1.1  christos }
    285   1.1  christos #endif
    286   1.1  christos 
    287   1.1  christos 
    288   1.1  christos 
    289   1.1  christos const struct hw_property *
    290   1.1  christos hw_next_property (const struct hw_property *property)
    291   1.1  christos {
    292   1.1  christos   /* find the property in the list */
    293   1.1  christos   struct hw *owner = property->owner;
    294   1.1  christos   struct hw_property_data *entry = owner->properties_of_hw;
    295   1.1  christos   while (entry != NULL && entry->property != property)
    296   1.1  christos     entry = entry->next;
    297   1.1  christos   /* now return the following property */
    298   1.1  christos   ASSERT (entry != NULL); /* must be a member! */
    299   1.1  christos   if (entry->next != NULL)
    300   1.1  christos     return entry->next->property;
    301   1.1  christos   else
    302   1.1  christos     return NULL;
    303   1.1  christos }
    304   1.1  christos 
    305   1.1  christos 
    306   1.1  christos const struct hw_property *
    307   1.1  christos hw_find_property (struct hw *me,
    308   1.1  christos 		  const char *property)
    309   1.1  christos {
    310   1.1  christos   if (me == NULL)
    311   1.1  christos     {
    312   1.1  christos       return NULL;
    313   1.1  christos     }
    314   1.1  christos   else if (property == NULL || strcmp (property, "") == 0)
    315   1.1  christos     {
    316   1.1  christos       if (me->properties_of_hw == NULL)
    317   1.1  christos 	return NULL;
    318   1.1  christos       else
    319   1.1  christos 	return me->properties_of_hw->property;
    320   1.1  christos     }
    321   1.1  christos   else
    322   1.1  christos     {
    323   1.1  christos       struct hw_property_data *entry = find_property_data (me, property);
    324   1.1  christos       if (entry != NULL)
    325   1.1  christos 	return entry->property;
    326   1.1  christos     }
    327   1.1  christos   return NULL;
    328   1.1  christos }
    329   1.1  christos 
    330   1.1  christos 
    331   1.1  christos void
    332   1.1  christos hw_add_array_property (struct hw *me,
    333   1.1  christos 		       const char *property,
    334   1.1  christos 		       const void *array,
    335   1.1  christos 		       int sizeof_array)
    336   1.1  christos {
    337   1.1  christos   hw_add_property (me, property, array_property,
    338   1.1  christos 		   array, sizeof_array, array, sizeof_array,
    339  1.11  christos 		   NULL, permanent_object);
    340   1.1  christos }
    341   1.1  christos 
    342   1.1  christos void
    343   1.1  christos hw_set_array_property (struct hw *me,
    344   1.1  christos 		       const char *property,
    345   1.1  christos 		       const void *array,
    346   1.1  christos 		       int sizeof_array)
    347   1.1  christos {
    348   1.1  christos   hw_set_property (me, property, array_property, array, sizeof_array);
    349   1.1  christos }
    350   1.1  christos 
    351   1.1  christos const struct hw_property *
    352   1.1  christos hw_find_array_property (struct hw *me,
    353   1.1  christos 			const char *property)
    354   1.1  christos {
    355   1.1  christos   const struct hw_property *node;
    356   1.1  christos   node = hw_find_property (me, property);
    357   1.1  christos   if (node == NULL)
    358   1.1  christos     hw_abort (me, "property \"%s\" not found", property);
    359   1.1  christos   if (node->type != array_property)
    360   1.1  christos     hw_abort (me, "property \"%s\" of wrong type (array)", property);
    361   1.1  christos   return node;
    362   1.1  christos }
    363   1.1  christos 
    364   1.1  christos 
    365   1.1  christos 
    366   1.1  christos void
    367   1.1  christos hw_add_boolean_property (struct hw *me,
    368   1.1  christos 			 const char *property,
    369   1.1  christos 			 int boolean)
    370   1.1  christos {
    371  1.10  christos   int32_t new_boolean = (boolean ? -1 : 0);
    372   1.1  christos   hw_add_property (me, property, boolean_property,
    373   1.1  christos 		   &new_boolean, sizeof (new_boolean),
    374   1.1  christos 		   &new_boolean, sizeof (new_boolean),
    375  1.11  christos 		   NULL, permanent_object);
    376   1.1  christos }
    377   1.1  christos 
    378   1.1  christos int
    379   1.1  christos hw_find_boolean_property (struct hw *me,
    380   1.1  christos 			  const char *property)
    381   1.1  christos {
    382   1.1  christos   const struct hw_property *node;
    383   1.1  christos   unsigned_cell boolean;
    384   1.1  christos   node = hw_find_property (me, property);
    385   1.1  christos   if (node == NULL)
    386   1.1  christos     hw_abort (me, "property \"%s\" not found", property);
    387   1.1  christos   if (node->type != boolean_property)
    388   1.1  christos     hw_abort (me, "property \"%s\" of wrong type (boolean)", property);
    389   1.1  christos   ASSERT (sizeof (boolean) == node->sizeof_array);
    390   1.1  christos   memcpy (&boolean, node->array, sizeof (boolean));
    391   1.1  christos   return boolean;
    392   1.1  christos }
    393   1.1  christos 
    394   1.1  christos 
    395   1.1  christos 
    396   1.1  christos #if 0
    397   1.1  christos void
    398   1.1  christos hw_add_ihandle_runtime_property (struct hw *me,
    399   1.1  christos 				 const char *property,
    400   1.1  christos 				 const ihandle_runtime_property_spec *ihandle)
    401   1.1  christos {
    402   1.1  christos   /* enter the full path as the init array */
    403   1.1  christos   hw_add_property (me, property, ihandle_property,
    404   1.1  christos 		   ihandle->full_path, strlen (ihandle->full_path) + 1,
    405   1.1  christos 		   NULL, 0,
    406  1.11  christos 		   NULL, permanent_object);
    407   1.1  christos }
    408   1.1  christos #endif
    409   1.1  christos 
    410   1.1  christos #if 0
    411   1.1  christos void
    412   1.1  christos hw_find_ihandle_runtime_property (struct hw *me,
    413   1.1  christos 				  const char *property,
    414   1.1  christos 				  ihandle_runtime_property_spec *ihandle)
    415   1.1  christos {
    416   1.1  christos   struct hw_property_data *entry = find_property_data (me, property);
    417   1.1  christos   if (entry == NULL)
    418   1.1  christos     hw_abort (me, "property \"%s\" not found", property);
    419   1.1  christos   if (entry->property->type != ihandle_property
    420  1.11  christos       || entry->property->disposition != permanent_object)
    421   1.1  christos     hw_abort (me, "property \"%s\" of wrong type", property);
    422   1.1  christos   ASSERT (entry->init_array != NULL);
    423   1.1  christos   /* the full path */
    424   1.1  christos   ihandle->full_path = entry->init_array;
    425   1.1  christos }
    426   1.1  christos #endif
    427   1.1  christos 
    428   1.1  christos 
    429   1.1  christos 
    430   1.1  christos #if 0
    431   1.1  christos void
    432   1.1  christos hw_set_ihandle_property (struct hw *me,
    433   1.1  christos 			 const char *property,
    434   1.1  christos 			 hw_instance *ihandle)
    435   1.1  christos {
    436   1.1  christos   unsigned_cell cells;
    437   1.1  christos   cells = H2BE_cell (hw_instance_to_external (ihandle));
    438   1.1  christos   hw_set_property (me, property, ihandle_property,
    439   1.1  christos 		   &cells, sizeof (cells));
    440   1.1  christos 
    441   1.1  christos }
    442   1.1  christos #endif
    443   1.1  christos 
    444   1.1  christos #if 0
    445   1.1  christos hw_instance *
    446   1.1  christos hw_find_ihandle_property (struct hw *me,
    447   1.1  christos 			  const char *property)
    448   1.1  christos {
    449   1.1  christos   const hw_property_data *node;
    450   1.1  christos   unsigned_cell ihandle;
    451   1.1  christos   hw_instance *instance;
    452   1.1  christos 
    453   1.1  christos   node = hw_find_property (me, property);
    454   1.1  christos   if (node == NULL)
    455   1.1  christos     hw_abort (me, "property \"%s\" not found", property);
    456   1.1  christos   if (node->type != ihandle_property)
    457   1.1  christos     hw_abort (me, "property \"%s\" of wrong type (ihandle)", property);
    458   1.1  christos   if (node->array == NULL)
    459   1.1  christos     hw_abort (me, "runtime property \"%s\" not yet initialized", property);
    460   1.1  christos 
    461   1.1  christos   ASSERT (sizeof (ihandle) == node->sizeof_array);
    462   1.1  christos   memcpy (&ihandle, node->array, sizeof (ihandle));
    463   1.1  christos   instance = external_to_hw_instance (me, BE2H_cell (ihandle));
    464   1.1  christos   ASSERT (instance != NULL);
    465   1.1  christos   return instance;
    466   1.1  christos }
    467   1.1  christos #endif
    468   1.1  christos 
    469   1.1  christos 
    470   1.1  christos void
    471   1.1  christos hw_add_integer_property (struct hw *me,
    472   1.1  christos 			 const char *property,
    473   1.1  christos 			 signed_cell integer)
    474   1.1  christos {
    475   1.1  christos   H2BE (integer);
    476   1.1  christos   hw_add_property (me, property, integer_property,
    477   1.1  christos 		   &integer, sizeof (integer),
    478   1.1  christos 		   &integer, sizeof (integer),
    479  1.11  christos 		   NULL, permanent_object);
    480   1.1  christos }
    481   1.1  christos 
    482   1.1  christos signed_cell
    483   1.1  christos hw_find_integer_property (struct hw *me,
    484   1.1  christos 			  const char *property)
    485   1.1  christos {
    486   1.1  christos   const struct hw_property *node;
    487   1.1  christos   signed_cell integer;
    488   1.1  christos   node = hw_find_property (me, property);
    489   1.1  christos   if (node == NULL)
    490   1.1  christos     hw_abort (me, "property \"%s\" not found", property);
    491   1.1  christos   if (node->type != integer_property)
    492   1.1  christos     hw_abort (me, "property \"%s\" of wrong type (integer)", property);
    493   1.1  christos   ASSERT (sizeof (integer) == node->sizeof_array);
    494   1.1  christos   memcpy (&integer, node->array, sizeof (integer));
    495   1.1  christos   return BE2H_cell (integer);
    496   1.1  christos }
    497   1.1  christos 
    498   1.1  christos int
    499   1.1  christos hw_find_integer_array_property (struct hw *me,
    500   1.1  christos 				const char *property,
    501   1.1  christos 				unsigned index,
    502   1.1  christos 				signed_cell *integer)
    503   1.1  christos {
    504   1.1  christos   const struct hw_property *node;
    505   1.1  christos   int sizeof_integer = sizeof (*integer);
    506   1.1  christos   signed_cell *cell;
    507   1.1  christos 
    508   1.1  christos   /* check things sane */
    509   1.1  christos   node = hw_find_property (me, property);
    510   1.1  christos   if (node == NULL)
    511   1.1  christos     hw_abort (me, "property \"%s\" not found", property);
    512   1.1  christos   if (node->type != integer_property
    513   1.1  christos       && node->type != array_property)
    514   1.1  christos     hw_abort (me, "property \"%s\" of wrong type (integer or array)", property);
    515   1.1  christos   if ((node->sizeof_array % sizeof_integer) != 0)
    516   1.1  christos     hw_abort (me, "property \"%s\" contains an incomplete number of cells", property);
    517   1.1  christos   if (node->sizeof_array <= sizeof_integer * index)
    518   1.1  christos     return 0;
    519   1.1  christos 
    520   1.1  christos   /* Find and convert the value */
    521   1.1  christos   cell = ((signed_cell*)node->array) + index;
    522   1.1  christos   *integer = BE2H_cell (*cell);
    523   1.1  christos 
    524   1.1  christos   return node->sizeof_array / sizeof_integer;
    525   1.1  christos }
    526   1.1  christos 
    527   1.1  christos 
    528   1.1  christos static unsigned_cell *
    529   1.1  christos unit_address_to_cells (const hw_unit *unit,
    530   1.1  christos 		       unsigned_cell *cell,
    531   1.1  christos 		       int nr_cells)
    532   1.1  christos {
    533   1.1  christos   int i;
    534   1.1  christos   ASSERT (nr_cells == unit->nr_cells);
    535   1.1  christos   for (i = 0; i < unit->nr_cells; i++)
    536   1.1  christos     {
    537   1.1  christos       *cell = H2BE_cell (unit->cells[i]);
    538   1.1  christos       cell += 1;
    539   1.1  christos     }
    540   1.1  christos   return cell;
    541   1.1  christos }
    542   1.1  christos 
    543   1.1  christos 
    544   1.1  christos static const unsigned_cell *
    545   1.1  christos cells_to_unit_address (const unsigned_cell *cell,
    546   1.1  christos 		       hw_unit *unit,
    547   1.1  christos 		       int nr_cells)
    548   1.1  christos {
    549   1.1  christos   int i;
    550   1.1  christos   memset (unit, 0, sizeof (*unit));
    551   1.1  christos   unit->nr_cells = nr_cells;
    552   1.1  christos   for (i = 0; i < unit->nr_cells; i++)
    553   1.1  christos     {
    554   1.1  christos       unit->cells[i] = BE2H_cell (*cell);
    555   1.1  christos       cell += 1;
    556   1.1  christos     }
    557   1.1  christos   return cell;
    558   1.1  christos }
    559   1.1  christos 
    560   1.1  christos 
    561   1.1  christos static unsigned
    562   1.1  christos nr_range_property_cells (struct hw *me,
    563   1.1  christos 			 int nr_ranges)
    564   1.1  christos {
    565   1.1  christos   return ((hw_unit_nr_address_cells (me)
    566   1.1  christos 	   + hw_unit_nr_address_cells (hw_parent (me))
    567   1.1  christos 	   + hw_unit_nr_size_cells (me))
    568   1.1  christos 	  ) * nr_ranges;
    569   1.1  christos }
    570   1.1  christos 
    571   1.1  christos void
    572   1.1  christos hw_add_range_array_property (struct hw *me,
    573   1.1  christos 			     const char *property,
    574   1.1  christos 			     const range_property_spec *ranges,
    575   1.1  christos 			     unsigned nr_ranges)
    576   1.1  christos {
    577   1.1  christos   unsigned sizeof_cells = (nr_range_property_cells (me, nr_ranges)
    578   1.1  christos 			   * sizeof (unsigned_cell));
    579   1.1  christos   unsigned_cell *cells = hw_zalloc (me, sizeof_cells);
    580   1.1  christos   unsigned_cell *cell;
    581   1.1  christos   int i;
    582   1.1  christos 
    583   1.1  christos   /* copy the property elements over */
    584   1.1  christos   cell = cells;
    585   1.1  christos   for (i = 0; i < nr_ranges; i++)
    586   1.1  christos     {
    587   1.1  christos       const range_property_spec *range = &ranges[i];
    588   1.1  christos       /* copy the child address */
    589   1.1  christos       cell = unit_address_to_cells (&range->child_address, cell,
    590   1.1  christos 				    hw_unit_nr_address_cells (me));
    591   1.1  christos       /* copy the parent address */
    592   1.1  christos       cell = unit_address_to_cells (&range->parent_address, cell,
    593   1.1  christos 				    hw_unit_nr_address_cells (hw_parent (me)));
    594   1.1  christos       /* copy the size */
    595   1.1  christos       cell = unit_address_to_cells (&range->size, cell,
    596   1.1  christos 				    hw_unit_nr_size_cells (me));
    597   1.1  christos     }
    598   1.1  christos   ASSERT (cell == &cells[nr_range_property_cells (me, nr_ranges)]);
    599   1.1  christos 
    600   1.1  christos   /* add it */
    601   1.1  christos   hw_add_property (me, property, range_array_property,
    602   1.1  christos 		   cells, sizeof_cells,
    603   1.1  christos 		   cells, sizeof_cells,
    604  1.11  christos 		   NULL, permanent_object);
    605   1.1  christos 
    606   1.1  christos   hw_free (me, cells);
    607   1.1  christos }
    608   1.1  christos 
    609   1.1  christos int
    610   1.1  christos hw_find_range_array_property (struct hw *me,
    611   1.1  christos 			      const char *property,
    612   1.1  christos 			      unsigned index,
    613   1.1  christos 			      range_property_spec *range)
    614   1.1  christos {
    615   1.1  christos   const struct hw_property *node;
    616   1.1  christos   unsigned sizeof_entry = (nr_range_property_cells (me, 1)
    617   1.1  christos 			   * sizeof (unsigned_cell));
    618   1.1  christos   const unsigned_cell *cells;
    619   1.1  christos 
    620   1.1  christos   /* locate the property */
    621   1.1  christos   node = hw_find_property (me, property);
    622   1.1  christos   if (node == NULL)
    623   1.1  christos     hw_abort (me, "property \"%s\" not found", property);
    624   1.1  christos   if (node->type != range_array_property)
    625   1.1  christos     hw_abort (me, "property \"%s\" of wrong type (range array)", property);
    626   1.1  christos 
    627   1.1  christos   /* aligned ? */
    628   1.1  christos   if ((node->sizeof_array % sizeof_entry) != 0)
    629   1.1  christos     hw_abort (me, "property \"%s\" contains an incomplete number of entries",
    630   1.1  christos 	      property);
    631   1.1  christos 
    632   1.1  christos   /* within bounds? */
    633   1.1  christos   if (node->sizeof_array < sizeof_entry * (index + 1))
    634   1.1  christos     return 0;
    635   1.1  christos 
    636   1.1  christos   /* find the range of interest */
    637   1.1  christos   cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
    638   1.1  christos 
    639   1.1  christos   /* copy the child address out - converting as we go */
    640   1.1  christos   cells = cells_to_unit_address (cells, &range->child_address,
    641   1.1  christos 				 hw_unit_nr_address_cells (me));
    642   1.1  christos 
    643   1.1  christos   /* copy the parent address out - converting as we go */
    644   1.1  christos   cells = cells_to_unit_address (cells, &range->parent_address,
    645   1.1  christos 				 hw_unit_nr_address_cells (hw_parent (me)));
    646   1.1  christos 
    647   1.1  christos   /* copy the size - converting as we go */
    648   1.1  christos   cells = cells_to_unit_address (cells, &range->size,
    649   1.1  christos 				 hw_unit_nr_size_cells (me));
    650   1.1  christos 
    651   1.1  christos   return node->sizeof_array / sizeof_entry;
    652   1.1  christos }
    653   1.1  christos 
    654   1.1  christos 
    655   1.1  christos static unsigned
    656   1.1  christos nr_reg_property_cells (struct hw *me,
    657   1.1  christos 		       int nr_regs)
    658   1.1  christos {
    659   1.1  christos   return (hw_unit_nr_address_cells (hw_parent (me))
    660   1.1  christos 	  + hw_unit_nr_size_cells (hw_parent (me))
    661   1.1  christos 	  ) * nr_regs;
    662   1.1  christos }
    663   1.1  christos 
    664   1.1  christos void
    665   1.1  christos hw_add_reg_array_property (struct hw *me,
    666   1.1  christos 			   const char *property,
    667   1.1  christos 			   const reg_property_spec *regs,
    668   1.1  christos 			   unsigned nr_regs)
    669   1.1  christos {
    670   1.1  christos   unsigned sizeof_cells = (nr_reg_property_cells (me, nr_regs)
    671   1.1  christos 			   * sizeof (unsigned_cell));
    672   1.1  christos   unsigned_cell *cells = hw_zalloc (me, sizeof_cells);
    673   1.1  christos   unsigned_cell *cell;
    674   1.1  christos   int i;
    675   1.1  christos 
    676   1.1  christos   /* copy the property elements over */
    677   1.1  christos   cell = cells;
    678   1.1  christos   for (i = 0; i < nr_regs; i++)
    679   1.1  christos     {
    680   1.1  christos       const reg_property_spec *reg = &regs[i];
    681   1.1  christos       /* copy the address */
    682   1.1  christos       cell = unit_address_to_cells (&reg->address, cell,
    683   1.1  christos 				    hw_unit_nr_address_cells (hw_parent (me)));
    684   1.1  christos       /* copy the size */
    685   1.1  christos       cell = unit_address_to_cells (&reg->size, cell,
    686   1.1  christos 				    hw_unit_nr_size_cells (hw_parent (me)));
    687   1.1  christos     }
    688   1.1  christos   ASSERT (cell == &cells[nr_reg_property_cells (me, nr_regs)]);
    689   1.1  christos 
    690   1.1  christos   /* add it */
    691   1.1  christos   hw_add_property (me, property, reg_array_property,
    692   1.1  christos 		   cells, sizeof_cells,
    693   1.1  christos 		   cells, sizeof_cells,
    694  1.11  christos 		   NULL, permanent_object);
    695   1.1  christos 
    696   1.1  christos   hw_free (me, cells);
    697   1.1  christos }
    698   1.1  christos 
    699   1.1  christos int
    700   1.1  christos hw_find_reg_array_property (struct hw *me,
    701   1.1  christos 			    const char *property,
    702   1.1  christos 			    unsigned index,
    703   1.1  christos 			    reg_property_spec *reg)
    704   1.1  christos {
    705   1.1  christos   const struct hw_property *node;
    706   1.1  christos   unsigned sizeof_entry = (nr_reg_property_cells (me, 1)
    707   1.1  christos 			   * sizeof (unsigned_cell));
    708   1.1  christos   const unsigned_cell *cells;
    709   1.1  christos 
    710   1.1  christos   /* locate the property */
    711   1.1  christos   node = hw_find_property (me, property);
    712   1.1  christos   if (node == NULL)
    713   1.1  christos     hw_abort (me, "property \"%s\" not found", property);
    714   1.1  christos   if (node->type != reg_array_property)
    715   1.1  christos     hw_abort (me, "property \"%s\" of wrong type (reg array)", property);
    716   1.1  christos 
    717   1.1  christos   /* aligned ? */
    718   1.1  christos   if ((node->sizeof_array % sizeof_entry) != 0)
    719   1.1  christos     hw_abort (me, "property \"%s\" contains an incomplete number of entries",
    720   1.1  christos 	      property);
    721   1.1  christos 
    722   1.1  christos   /* within bounds? */
    723   1.1  christos   if (node->sizeof_array < sizeof_entry * (index + 1))
    724   1.1  christos     return 0;
    725   1.1  christos 
    726   1.1  christos   /* find the range of interest */
    727   1.1  christos   cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
    728   1.1  christos 
    729   1.1  christos   /* copy the address out - converting as we go */
    730   1.1  christos   cells = cells_to_unit_address (cells, &reg->address,
    731   1.1  christos 				 hw_unit_nr_address_cells (hw_parent (me)));
    732   1.1  christos 
    733   1.1  christos   /* copy the size out - converting as we go */
    734   1.1  christos   cells = cells_to_unit_address (cells, &reg->size,
    735   1.1  christos 				 hw_unit_nr_size_cells (hw_parent (me)));
    736   1.1  christos 
    737   1.1  christos   return node->sizeof_array / sizeof_entry;
    738   1.1  christos }
    739   1.1  christos 
    740   1.1  christos 
    741   1.1  christos void
    742   1.1  christos hw_add_string_property (struct hw *me,
    743   1.1  christos 			const char *property,
    744   1.1  christos 			const char *string)
    745   1.1  christos {
    746   1.1  christos   hw_add_property (me, property, string_property,
    747   1.1  christos 		   string, strlen (string) + 1,
    748   1.1  christos 		   string, strlen (string) + 1,
    749  1.11  christos 		   NULL, permanent_object);
    750   1.1  christos }
    751   1.1  christos 
    752   1.1  christos const char *
    753   1.1  christos hw_find_string_property (struct hw *me,
    754   1.1  christos 			 const char *property)
    755   1.1  christos {
    756   1.1  christos   const struct hw_property *node;
    757   1.1  christos   const char *string;
    758   1.1  christos   node = hw_find_property (me, property);
    759   1.1  christos   if (node == NULL)
    760   1.1  christos     hw_abort (me, "property \"%s\" not found", property);
    761   1.1  christos   if (node->type != string_property)
    762   1.1  christos     hw_abort (me, "property \"%s\" of wrong type (string)", property);
    763   1.1  christos   string = node->array;
    764   1.1  christos   ASSERT (strlen (string) + 1 == node->sizeof_array);
    765   1.1  christos   return string;
    766   1.1  christos }
    767   1.1  christos 
    768   1.1  christos void
    769   1.1  christos hw_add_string_array_property (struct hw *me,
    770   1.1  christos 			      const char *property,
    771   1.1  christos 			      const string_property_spec *strings,
    772   1.1  christos 			      unsigned nr_strings)
    773   1.1  christos {
    774   1.1  christos   int sizeof_array;
    775   1.1  christos   int string_nr;
    776   1.1  christos   char *array;
    777   1.1  christos   char *chp;
    778   1.1  christos   if (nr_strings == 0)
    779   1.1  christos     hw_abort (me, "property \"%s\" must be non-null", property);
    780   1.1  christos   /* total up the size of the needed array */
    781   1.1  christos   for (sizeof_array = 0, string_nr = 0;
    782   1.1  christos        string_nr < nr_strings;
    783   1.1  christos        string_nr ++)
    784   1.1  christos     {
    785   1.1  christos       sizeof_array += strlen (strings[string_nr]) + 1;
    786   1.1  christos     }
    787   1.1  christos   /* create the array */
    788   1.1  christos   array = (char*) hw_zalloc (me, sizeof_array);
    789   1.1  christos   chp = array;
    790   1.1  christos   for (string_nr = 0;
    791   1.1  christos        string_nr < nr_strings;
    792   1.1  christos        string_nr++)
    793   1.1  christos     {
    794   1.1  christos       strcpy (chp, strings[string_nr]);
    795   1.1  christos       chp += strlen (chp) + 1;
    796   1.1  christos     }
    797   1.1  christos   ASSERT (chp == array + sizeof_array);
    798   1.1  christos   /* now enter it */
    799   1.1  christos   hw_add_property (me, property, string_array_property,
    800   1.1  christos 		   array, sizeof_array,
    801   1.1  christos 		   array, sizeof_array,
    802  1.11  christos 		   NULL, permanent_object);
    803   1.1  christos }
    804   1.1  christos 
    805   1.1  christos int
    806   1.1  christos hw_find_string_array_property (struct hw *me,
    807   1.1  christos 			       const char *property,
    808   1.1  christos 			       unsigned index,
    809   1.1  christos 			       string_property_spec *string)
    810   1.1  christos {
    811   1.1  christos   const struct hw_property *node;
    812   1.1  christos   node = hw_find_property (me, property);
    813   1.1  christos   if (node == NULL)
    814   1.1  christos     hw_abort (me, "property \"%s\" not found", property);
    815   1.1  christos   switch (node->type)
    816   1.1  christos     {
    817   1.1  christos     default:
    818   1.1  christos       hw_abort (me, "property \"%s\" of wrong type", property);
    819   1.1  christos       break;
    820   1.1  christos     case string_property:
    821   1.1  christos       if (index == 0)
    822   1.1  christos 	{
    823   1.1  christos 	  *string = node->array;
    824   1.1  christos 	  ASSERT (strlen (*string) + 1 == node->sizeof_array);
    825   1.1  christos 	  return 1;
    826   1.1  christos 	}
    827   1.1  christos       break;
    828   1.1  christos     case array_property:
    829   1.1  christos       if (node->sizeof_array == 0
    830   1.1  christos 	  || ((char*)node->array)[node->sizeof_array - 1] != '\0')
    831   1.1  christos 	hw_abort (me, "property \"%s\" invalid for string array", property);
    832  1.11  christos       ATTRIBUTE_FALLTHROUGH;
    833   1.1  christos     case string_array_property:
    834   1.1  christos       ASSERT (node->sizeof_array > 0);
    835   1.1  christos       ASSERT (((char*)node->array)[node->sizeof_array - 1] == '\0');
    836   1.1  christos       {
    837   1.1  christos 	const char *chp = node->array;
    838   1.1  christos 	int nr_entries = 0;
    839   1.1  christos 	/* count the number of strings, keeping an eye out for the one
    840   1.1  christos 	   we're looking for */
    841   1.1  christos 	*string = chp;
    842   1.1  christos 	do
    843   1.1  christos 	  {
    844   1.1  christos 	    if (*chp == '\0')
    845   1.1  christos 	      {
    846   1.1  christos 		/* next string */
    847   1.1  christos 		nr_entries++;
    848   1.1  christos 		chp++;
    849   1.1  christos 		if (nr_entries == index)
    850   1.1  christos 		  *string = chp;
    851   1.1  christos 	      }
    852   1.1  christos 	    else
    853   1.1  christos 	      {
    854   1.1  christos 		chp++;
    855   1.1  christos 	      }
    856   1.1  christos 	  } while (chp < (char*)node->array + node->sizeof_array);
    857   1.1  christos 	if (index < nr_entries)
    858   1.1  christos 	  return nr_entries;
    859   1.1  christos 	else
    860   1.1  christos 	  {
    861   1.1  christos 	    *string = NULL;
    862   1.1  christos 	    return 0;
    863   1.1  christos 	  }
    864   1.1  christos       }
    865   1.1  christos       break;
    866   1.1  christos     }
    867   1.1  christos   return 0;
    868   1.1  christos }
    869   1.1  christos 
    870   1.1  christos void
    871   1.1  christos hw_add_duplicate_property (struct hw *me,
    872   1.1  christos 			   const char *property,
    873   1.1  christos 			   const struct hw_property *original)
    874   1.1  christos {
    875   1.1  christos   struct hw_property_data *master;
    876  1.11  christos   if (original->disposition != permanent_object)
    877  1.11  christos     hw_abort (me, "Can only duplicate permanent objects");
    878   1.1  christos   /* find the original's master */
    879   1.1  christos   master = original->owner->properties_of_hw;
    880   1.1  christos   while (master->property != original)
    881   1.1  christos     {
    882   1.1  christos       master = master->next;
    883   1.1  christos       ASSERT (master != NULL);
    884   1.1  christos     }
    885   1.1  christos   /* now duplicate it */
    886   1.1  christos   hw_add_property (me, property,
    887   1.1  christos 		   original->type,
    888   1.1  christos 		   master->init_array, master->sizeof_init_array,
    889   1.1  christos 		   original->array, original->sizeof_array,
    890  1.11  christos 		   original, permanent_object);
    891   1.1  christos }
    892