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