14e98e3e1Schristos /* The common simulator framework for GDB, the GNU Debugger. 24e98e3e1Schristos 3*88241920Schristos Copyright 2002-2024 Free Software Foundation, Inc. 44e98e3e1Schristos 54e98e3e1Schristos Contributed by Andrew Cagney and Red Hat. 64e98e3e1Schristos 74e98e3e1Schristos This file is part of GDB. 84e98e3e1Schristos 94e98e3e1Schristos This program is free software; you can redistribute it and/or modify 104e98e3e1Schristos it under the terms of the GNU General Public License as published by 114e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 124e98e3e1Schristos (at your option) any later version. 134e98e3e1Schristos 144e98e3e1Schristos This program is distributed in the hope that it will be useful, 154e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 164e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 174e98e3e1Schristos GNU General Public License for more details. 184e98e3e1Schristos 194e98e3e1Schristos You should have received a copy of the GNU General Public License 204e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 214e98e3e1Schristos 224b169a6bSchristos /* This must come before any other includes. */ 234b169a6bSchristos #include "defs.h" 244b169a6bSchristos 254b169a6bSchristos #include <string.h> 264b169a6bSchristos 274e98e3e1Schristos #include "hw-main.h" 284e98e3e1Schristos #include "hw-base.h" 294e98e3e1Schristos 304e98e3e1Schristos #include "sim-io.h" 314e98e3e1Schristos #include "sim-assert.h" 324e98e3e1Schristos 334e98e3e1Schristos /* property entries */ 344e98e3e1Schristos 354e98e3e1Schristos struct hw_property_data 364e98e3e1Schristos { 374e98e3e1Schristos struct hw_property_data *next; 384e98e3e1Schristos struct hw_property *property; 394e98e3e1Schristos const void *init_array; 404e98e3e1Schristos unsigned sizeof_init_array; 414e98e3e1Schristos }; 424e98e3e1Schristos 434e98e3e1Schristos void 444e98e3e1Schristos create_hw_property_data (struct hw *me) 454e98e3e1Schristos { 464e98e3e1Schristos } 474e98e3e1Schristos 484e98e3e1Schristos void 494e98e3e1Schristos delete_hw_property_data (struct hw *me) 504e98e3e1Schristos { 514e98e3e1Schristos } 524e98e3e1Schristos 534e98e3e1Schristos 544e98e3e1Schristos /* Device Properties: */ 554e98e3e1Schristos 564e98e3e1Schristos static struct hw_property_data * 574e98e3e1Schristos find_property_data (struct hw *me, 584e98e3e1Schristos const char *property) 594e98e3e1Schristos { 604e98e3e1Schristos struct hw_property_data *entry; 614e98e3e1Schristos ASSERT (property != NULL); 624e98e3e1Schristos entry = me->properties_of_hw; 634e98e3e1Schristos while (entry != NULL) 644e98e3e1Schristos { 654e98e3e1Schristos if (strcmp (entry->property->name, property) == 0) 664e98e3e1Schristos return entry; 674e98e3e1Schristos entry = entry->next; 684e98e3e1Schristos } 694e98e3e1Schristos return NULL; 704e98e3e1Schristos } 714e98e3e1Schristos 724e98e3e1Schristos 734e98e3e1Schristos static void 744e98e3e1Schristos hw_add_property (struct hw *me, 754e98e3e1Schristos const char *property, 764e98e3e1Schristos hw_property_type type, 774e98e3e1Schristos const void *init_array, 784e98e3e1Schristos unsigned sizeof_init_array, 794e98e3e1Schristos const void *array, 804e98e3e1Schristos unsigned sizeof_array, 814e98e3e1Schristos const struct hw_property *original, 824e98e3e1Schristos object_disposition disposition) 834e98e3e1Schristos { 844e98e3e1Schristos struct hw_property_data *new_entry = NULL; 854e98e3e1Schristos struct hw_property *new_value = NULL; 864e98e3e1Schristos 874e98e3e1Schristos /* find the list end */ 884e98e3e1Schristos struct hw_property_data **insertion_point = &me->properties_of_hw; 894e98e3e1Schristos while (*insertion_point != NULL) 904e98e3e1Schristos { 914e98e3e1Schristos if (strcmp ((*insertion_point)->property->name, property) == 0) 924e98e3e1Schristos return; 934e98e3e1Schristos insertion_point = &(*insertion_point)->next; 944e98e3e1Schristos } 954e98e3e1Schristos 964e98e3e1Schristos /* create a new value */ 974e98e3e1Schristos new_value = HW_ZALLOC (me, struct hw_property); 984e98e3e1Schristos new_value->name = (char *) strdup (property); 994e98e3e1Schristos new_value->type = type; 1004e98e3e1Schristos if (sizeof_array > 0) 1014e98e3e1Schristos { 1024e98e3e1Schristos void *new_array = hw_zalloc (me, sizeof_array); 1034e98e3e1Schristos memcpy (new_array, array, sizeof_array); 1044e98e3e1Schristos new_value->array = new_array; 1054e98e3e1Schristos new_value->sizeof_array = sizeof_array; 1064e98e3e1Schristos } 1074e98e3e1Schristos new_value->owner = me; 1084e98e3e1Schristos new_value->original = original; 1094e98e3e1Schristos new_value->disposition = disposition; 1104e98e3e1Schristos 1114e98e3e1Schristos /* insert the value into the list */ 1124e98e3e1Schristos new_entry = HW_ZALLOC (me, struct hw_property_data); 1134e98e3e1Schristos *insertion_point = new_entry; 1144e98e3e1Schristos if (sizeof_init_array > 0) 1154e98e3e1Schristos { 1164e98e3e1Schristos void *new_init_array = hw_zalloc (me, sizeof_init_array); 1174e98e3e1Schristos memcpy (new_init_array, init_array, sizeof_init_array); 1184e98e3e1Schristos new_entry->init_array = new_init_array; 1194e98e3e1Schristos new_entry->sizeof_init_array = sizeof_init_array; 1204e98e3e1Schristos } 1214e98e3e1Schristos new_entry->property = new_value; 1224e98e3e1Schristos } 1234e98e3e1Schristos 1244e98e3e1Schristos 1254e98e3e1Schristos static void 1264e98e3e1Schristos hw_set_property (struct hw *me, 1274e98e3e1Schristos const char *property, 1284e98e3e1Schristos hw_property_type type, 1294e98e3e1Schristos const void *array, 1304e98e3e1Schristos int sizeof_array) 1314e98e3e1Schristos { 1324e98e3e1Schristos /* find the property */ 1334e98e3e1Schristos struct hw_property_data *entry = find_property_data (me, property); 1344e98e3e1Schristos if (entry != NULL) 1354e98e3e1Schristos { 1364e98e3e1Schristos /* existing property - update it */ 1374e98e3e1Schristos void *new_array = 0; 1384e98e3e1Schristos struct hw_property *value = entry->property; 1394e98e3e1Schristos /* check the type matches */ 1404e98e3e1Schristos if (value->type != type) 1414e98e3e1Schristos hw_abort (me, "conflict between type of new and old value for property %s", property); 1424e98e3e1Schristos /* replace its value */ 1434e98e3e1Schristos if (value->array != NULL) 1444e98e3e1Schristos hw_free (me, (void*)value->array); 1454e98e3e1Schristos new_array = (sizeof_array > 0 1464e98e3e1Schristos ? hw_zalloc (me, sizeof_array) 1474e98e3e1Schristos : (void*)0); 1484e98e3e1Schristos value->array = new_array; 1494e98e3e1Schristos value->sizeof_array = sizeof_array; 1504e98e3e1Schristos if (sizeof_array > 0) 1514e98e3e1Schristos memcpy (new_array, array, sizeof_array); 1524e98e3e1Schristos return; 1534e98e3e1Schristos } 1544e98e3e1Schristos else 1554e98e3e1Schristos { 1564e98e3e1Schristos /* new property - create it */ 1574e98e3e1Schristos hw_add_property (me, property, type, 1584e98e3e1Schristos NULL, 0, array, sizeof_array, 1594e98e3e1Schristos NULL, temporary_object); 1604e98e3e1Schristos } 1614e98e3e1Schristos } 1624e98e3e1Schristos 1634e98e3e1Schristos 1644e98e3e1Schristos #if 0 1654e98e3e1Schristos static void 1664e98e3e1Schristos clean_hw_properties (struct hw *me) 1674e98e3e1Schristos { 1684e98e3e1Schristos struct hw_property_data **delete_point = &me->properties_of_hw; 1694e98e3e1Schristos while (*delete_point != NULL) 1704e98e3e1Schristos { 1714e98e3e1Schristos struct hw_property_data *current = *delete_point; 1724e98e3e1Schristos switch (current->property->disposition) 1734e98e3e1Schristos { 174*88241920Schristos case permanent_object: 1754e98e3e1Schristos /* zap the current value, will be initialized later */ 1764e98e3e1Schristos ASSERT (current->init_array != NULL); 1774e98e3e1Schristos if (current->property->array != NULL) 1784e98e3e1Schristos { 1794e98e3e1Schristos hw_free (me, (void*)current->property->array); 1804e98e3e1Schristos current->property->array = NULL; 1814e98e3e1Schristos } 1824e98e3e1Schristos delete_point = &(*delete_point)->next; 1834e98e3e1Schristos break; 1844e98e3e1Schristos case temporary_object: 1854e98e3e1Schristos /* zap the actual property, was created during simulation run */ 1864e98e3e1Schristos ASSERT (current->init_array == NULL); 1874e98e3e1Schristos *delete_point = current->next; 1884e98e3e1Schristos if (current->property->array != NULL) 1894e98e3e1Schristos hw_free (me, (void*)current->property->array); 1904e98e3e1Schristos hw_free (me, current->property); 1914e98e3e1Schristos hw_free (me, current); 1924e98e3e1Schristos break; 1934e98e3e1Schristos } 1944e98e3e1Schristos } 1954e98e3e1Schristos } 1964e98e3e1Schristos #endif 1974e98e3e1Schristos 1984e98e3e1Schristos #if 0 1994e98e3e1Schristos void 2004e98e3e1Schristos hw_init_static_properties (SIM_DESC sd, 2014e98e3e1Schristos struct hw *me, 2024e98e3e1Schristos void *data) 2034e98e3e1Schristos { 2044e98e3e1Schristos struct hw_property_data *property; 2054e98e3e1Schristos for (property = me->properties_of_hw; 2064e98e3e1Schristos property != NULL; 2074e98e3e1Schristos property = property->next) 2084e98e3e1Schristos { 2094e98e3e1Schristos ASSERT (property->init_array != NULL); 2104e98e3e1Schristos ASSERT (property->property->array == NULL); 211*88241920Schristos ASSERT (property->property->disposition == permanent_object); 2124e98e3e1Schristos switch (property->property->type) 2134e98e3e1Schristos { 2144e98e3e1Schristos case array_property: 2154e98e3e1Schristos case boolean_property: 2164e98e3e1Schristos case range_array_property: 2174e98e3e1Schristos case reg_array_property: 2184e98e3e1Schristos case string_property: 2194e98e3e1Schristos case string_array_property: 2204e98e3e1Schristos case integer_property: 2214e98e3e1Schristos /* delete the property, and replace it with the original */ 2224e98e3e1Schristos hw_set_property (me, property->property->name, 2234e98e3e1Schristos property->property->type, 2244e98e3e1Schristos property->init_array, 2254e98e3e1Schristos property->sizeof_init_array); 2264e98e3e1Schristos break; 2274e98e3e1Schristos #if 0 2284e98e3e1Schristos case ihandle_property: 2294e98e3e1Schristos break; 2304e98e3e1Schristos #endif 2314e98e3e1Schristos } 2324e98e3e1Schristos } 2334e98e3e1Schristos } 2344e98e3e1Schristos #endif 2354e98e3e1Schristos 2364e98e3e1Schristos 2374e98e3e1Schristos #if 0 2384e98e3e1Schristos void 2394e98e3e1Schristos hw_init_runtime_properties (SIM_DESC sd, 2404e98e3e1Schristos struct hw *me, 2414e98e3e1Schristos void *data) 2424e98e3e1Schristos { 2434e98e3e1Schristos struct hw_property_data *property; 2444e98e3e1Schristos for (property = me->properties_of_hw; 2454e98e3e1Schristos property != NULL; 2464e98e3e1Schristos property = property->next) 2474e98e3e1Schristos { 2484e98e3e1Schristos switch (property->property->disposition) 2494e98e3e1Schristos { 250*88241920Schristos case permanent_object: 2514e98e3e1Schristos switch (property->property->type) 2524e98e3e1Schristos { 2534e98e3e1Schristos #if 0 2544e98e3e1Schristos case ihandle_property: 2554e98e3e1Schristos { 2564e98e3e1Schristos struct hw_instance *ihandle; 2574e98e3e1Schristos ihandle_runtime_property_spec spec; 2584e98e3e1Schristos ASSERT (property->init_array != NULL); 2594e98e3e1Schristos ASSERT (property->property->array == NULL); 2604e98e3e1Schristos hw_find_ihandle_runtime_property (me, property->property->name, &spec); 2614e98e3e1Schristos ihandle = tree_instance (me, spec.full_path); 2624e98e3e1Schristos hw_set_ihandle_property (me, property->property->name, ihandle); 2634e98e3e1Schristos break; 2644e98e3e1Schristos } 2654e98e3e1Schristos #endif 2664e98e3e1Schristos case array_property: 2674e98e3e1Schristos case boolean_property: 2684e98e3e1Schristos case range_array_property: 2694e98e3e1Schristos case integer_property: 2704e98e3e1Schristos case reg_array_property: 2714e98e3e1Schristos case string_property: 2724e98e3e1Schristos case string_array_property: 2734e98e3e1Schristos ASSERT (property->init_array != NULL); 2744e98e3e1Schristos ASSERT (property->property->array != NULL); 2754e98e3e1Schristos break; 2764e98e3e1Schristos } 2774e98e3e1Schristos break; 2784e98e3e1Schristos case temporary_object: 2794e98e3e1Schristos ASSERT (property->init_array == NULL); 2804e98e3e1Schristos ASSERT (property->property->array != NULL); 2814e98e3e1Schristos break; 2824e98e3e1Schristos } 2834e98e3e1Schristos } 2844e98e3e1Schristos } 2854e98e3e1Schristos #endif 2864e98e3e1Schristos 2874e98e3e1Schristos 2884e98e3e1Schristos 2894e98e3e1Schristos const struct hw_property * 2904e98e3e1Schristos hw_next_property (const struct hw_property *property) 2914e98e3e1Schristos { 2924e98e3e1Schristos /* find the property in the list */ 2934e98e3e1Schristos struct hw *owner = property->owner; 2944e98e3e1Schristos struct hw_property_data *entry = owner->properties_of_hw; 2954e98e3e1Schristos while (entry != NULL && entry->property != property) 2964e98e3e1Schristos entry = entry->next; 2974e98e3e1Schristos /* now return the following property */ 2984e98e3e1Schristos ASSERT (entry != NULL); /* must be a member! */ 2994e98e3e1Schristos if (entry->next != NULL) 3004e98e3e1Schristos return entry->next->property; 3014e98e3e1Schristos else 3024e98e3e1Schristos return NULL; 3034e98e3e1Schristos } 3044e98e3e1Schristos 3054e98e3e1Schristos 3064e98e3e1Schristos const struct hw_property * 3074e98e3e1Schristos hw_find_property (struct hw *me, 3084e98e3e1Schristos const char *property) 3094e98e3e1Schristos { 3104e98e3e1Schristos if (me == NULL) 3114e98e3e1Schristos { 3124e98e3e1Schristos return NULL; 3134e98e3e1Schristos } 3144e98e3e1Schristos else if (property == NULL || strcmp (property, "") == 0) 3154e98e3e1Schristos { 3164e98e3e1Schristos if (me->properties_of_hw == NULL) 3174e98e3e1Schristos return NULL; 3184e98e3e1Schristos else 3194e98e3e1Schristos return me->properties_of_hw->property; 3204e98e3e1Schristos } 3214e98e3e1Schristos else 3224e98e3e1Schristos { 3234e98e3e1Schristos struct hw_property_data *entry = find_property_data (me, property); 3244e98e3e1Schristos if (entry != NULL) 3254e98e3e1Schristos return entry->property; 3264e98e3e1Schristos } 3274e98e3e1Schristos return NULL; 3284e98e3e1Schristos } 3294e98e3e1Schristos 3304e98e3e1Schristos 3314e98e3e1Schristos void 3324e98e3e1Schristos hw_add_array_property (struct hw *me, 3334e98e3e1Schristos const char *property, 3344e98e3e1Schristos const void *array, 3354e98e3e1Schristos int sizeof_array) 3364e98e3e1Schristos { 3374e98e3e1Schristos hw_add_property (me, property, array_property, 3384e98e3e1Schristos array, sizeof_array, array, sizeof_array, 339*88241920Schristos NULL, permanent_object); 3404e98e3e1Schristos } 3414e98e3e1Schristos 3424e98e3e1Schristos void 3434e98e3e1Schristos hw_set_array_property (struct hw *me, 3444e98e3e1Schristos const char *property, 3454e98e3e1Schristos const void *array, 3464e98e3e1Schristos int sizeof_array) 3474e98e3e1Schristos { 3484e98e3e1Schristos hw_set_property (me, property, array_property, array, sizeof_array); 3494e98e3e1Schristos } 3504e98e3e1Schristos 3514e98e3e1Schristos const struct hw_property * 3524e98e3e1Schristos hw_find_array_property (struct hw *me, 3534e98e3e1Schristos const char *property) 3544e98e3e1Schristos { 3554e98e3e1Schristos const struct hw_property *node; 3564e98e3e1Schristos node = hw_find_property (me, property); 3574e98e3e1Schristos if (node == NULL) 3584e98e3e1Schristos hw_abort (me, "property \"%s\" not found", property); 3594e98e3e1Schristos if (node->type != array_property) 3604e98e3e1Schristos hw_abort (me, "property \"%s\" of wrong type (array)", property); 3614e98e3e1Schristos return node; 3624e98e3e1Schristos } 3634e98e3e1Schristos 3644e98e3e1Schristos 3654e98e3e1Schristos 3664e98e3e1Schristos void 3674e98e3e1Schristos hw_add_boolean_property (struct hw *me, 3684e98e3e1Schristos const char *property, 3694e98e3e1Schristos int boolean) 3704e98e3e1Schristos { 3714b169a6bSchristos int32_t new_boolean = (boolean ? -1 : 0); 3724e98e3e1Schristos hw_add_property (me, property, boolean_property, 3734e98e3e1Schristos &new_boolean, sizeof (new_boolean), 3744e98e3e1Schristos &new_boolean, sizeof (new_boolean), 375*88241920Schristos NULL, permanent_object); 3764e98e3e1Schristos } 3774e98e3e1Schristos 3784e98e3e1Schristos int 3794e98e3e1Schristos hw_find_boolean_property (struct hw *me, 3804e98e3e1Schristos const char *property) 3814e98e3e1Schristos { 3824e98e3e1Schristos const struct hw_property *node; 3834e98e3e1Schristos unsigned_cell boolean; 3844e98e3e1Schristos node = hw_find_property (me, property); 3854e98e3e1Schristos if (node == NULL) 3864e98e3e1Schristos hw_abort (me, "property \"%s\" not found", property); 3874e98e3e1Schristos if (node->type != boolean_property) 3884e98e3e1Schristos hw_abort (me, "property \"%s\" of wrong type (boolean)", property); 3894e98e3e1Schristos ASSERT (sizeof (boolean) == node->sizeof_array); 3904e98e3e1Schristos memcpy (&boolean, node->array, sizeof (boolean)); 3914e98e3e1Schristos return boolean; 3924e98e3e1Schristos } 3934e98e3e1Schristos 3944e98e3e1Schristos 3954e98e3e1Schristos 3964e98e3e1Schristos #if 0 3974e98e3e1Schristos void 3984e98e3e1Schristos hw_add_ihandle_runtime_property (struct hw *me, 3994e98e3e1Schristos const char *property, 4004e98e3e1Schristos const ihandle_runtime_property_spec *ihandle) 4014e98e3e1Schristos { 4024e98e3e1Schristos /* enter the full path as the init array */ 4034e98e3e1Schristos hw_add_property (me, property, ihandle_property, 4044e98e3e1Schristos ihandle->full_path, strlen (ihandle->full_path) + 1, 4054e98e3e1Schristos NULL, 0, 406*88241920Schristos NULL, permanent_object); 4074e98e3e1Schristos } 4084e98e3e1Schristos #endif 4094e98e3e1Schristos 4104e98e3e1Schristos #if 0 4114e98e3e1Schristos void 4124e98e3e1Schristos hw_find_ihandle_runtime_property (struct hw *me, 4134e98e3e1Schristos const char *property, 4144e98e3e1Schristos ihandle_runtime_property_spec *ihandle) 4154e98e3e1Schristos { 4164e98e3e1Schristos struct hw_property_data *entry = find_property_data (me, property); 4174e98e3e1Schristos if (entry == NULL) 4184e98e3e1Schristos hw_abort (me, "property \"%s\" not found", property); 4194e98e3e1Schristos if (entry->property->type != ihandle_property 420*88241920Schristos || entry->property->disposition != permanent_object) 4214e98e3e1Schristos hw_abort (me, "property \"%s\" of wrong type", property); 4224e98e3e1Schristos ASSERT (entry->init_array != NULL); 4234e98e3e1Schristos /* the full path */ 4244e98e3e1Schristos ihandle->full_path = entry->init_array; 4254e98e3e1Schristos } 4264e98e3e1Schristos #endif 4274e98e3e1Schristos 4284e98e3e1Schristos 4294e98e3e1Schristos 4304e98e3e1Schristos #if 0 4314e98e3e1Schristos void 4324e98e3e1Schristos hw_set_ihandle_property (struct hw *me, 4334e98e3e1Schristos const char *property, 4344e98e3e1Schristos hw_instance *ihandle) 4354e98e3e1Schristos { 4364e98e3e1Schristos unsigned_cell cells; 4374e98e3e1Schristos cells = H2BE_cell (hw_instance_to_external (ihandle)); 4384e98e3e1Schristos hw_set_property (me, property, ihandle_property, 4394e98e3e1Schristos &cells, sizeof (cells)); 4404e98e3e1Schristos 4414e98e3e1Schristos } 4424e98e3e1Schristos #endif 4434e98e3e1Schristos 4444e98e3e1Schristos #if 0 4454e98e3e1Schristos hw_instance * 4464e98e3e1Schristos hw_find_ihandle_property (struct hw *me, 4474e98e3e1Schristos const char *property) 4484e98e3e1Schristos { 4494e98e3e1Schristos const hw_property_data *node; 4504e98e3e1Schristos unsigned_cell ihandle; 4514e98e3e1Schristos hw_instance *instance; 4524e98e3e1Schristos 4534e98e3e1Schristos node = hw_find_property (me, property); 4544e98e3e1Schristos if (node == NULL) 4554e98e3e1Schristos hw_abort (me, "property \"%s\" not found", property); 4564e98e3e1Schristos if (node->type != ihandle_property) 4574e98e3e1Schristos hw_abort (me, "property \"%s\" of wrong type (ihandle)", property); 4584e98e3e1Schristos if (node->array == NULL) 4594e98e3e1Schristos hw_abort (me, "runtime property \"%s\" not yet initialized", property); 4604e98e3e1Schristos 4614e98e3e1Schristos ASSERT (sizeof (ihandle) == node->sizeof_array); 4624e98e3e1Schristos memcpy (&ihandle, node->array, sizeof (ihandle)); 4634e98e3e1Schristos instance = external_to_hw_instance (me, BE2H_cell (ihandle)); 4644e98e3e1Schristos ASSERT (instance != NULL); 4654e98e3e1Schristos return instance; 4664e98e3e1Schristos } 4674e98e3e1Schristos #endif 4684e98e3e1Schristos 4694e98e3e1Schristos 4704e98e3e1Schristos void 4714e98e3e1Schristos hw_add_integer_property (struct hw *me, 4724e98e3e1Schristos const char *property, 4734e98e3e1Schristos signed_cell integer) 4744e98e3e1Schristos { 4754e98e3e1Schristos H2BE (integer); 4764e98e3e1Schristos hw_add_property (me, property, integer_property, 4774e98e3e1Schristos &integer, sizeof (integer), 4784e98e3e1Schristos &integer, sizeof (integer), 479*88241920Schristos NULL, permanent_object); 4804e98e3e1Schristos } 4814e98e3e1Schristos 4824e98e3e1Schristos signed_cell 4834e98e3e1Schristos hw_find_integer_property (struct hw *me, 4844e98e3e1Schristos const char *property) 4854e98e3e1Schristos { 4864e98e3e1Schristos const struct hw_property *node; 4874e98e3e1Schristos signed_cell integer; 4884e98e3e1Schristos node = hw_find_property (me, property); 4894e98e3e1Schristos if (node == NULL) 4904e98e3e1Schristos hw_abort (me, "property \"%s\" not found", property); 4914e98e3e1Schristos if (node->type != integer_property) 4924e98e3e1Schristos hw_abort (me, "property \"%s\" of wrong type (integer)", property); 4934e98e3e1Schristos ASSERT (sizeof (integer) == node->sizeof_array); 4944e98e3e1Schristos memcpy (&integer, node->array, sizeof (integer)); 4954e98e3e1Schristos return BE2H_cell (integer); 4964e98e3e1Schristos } 4974e98e3e1Schristos 4984e98e3e1Schristos int 4994e98e3e1Schristos hw_find_integer_array_property (struct hw *me, 5004e98e3e1Schristos const char *property, 5014e98e3e1Schristos unsigned index, 5024e98e3e1Schristos signed_cell *integer) 5034e98e3e1Schristos { 5044e98e3e1Schristos const struct hw_property *node; 5054e98e3e1Schristos int sizeof_integer = sizeof (*integer); 5064e98e3e1Schristos signed_cell *cell; 5074e98e3e1Schristos 5084e98e3e1Schristos /* check things sane */ 5094e98e3e1Schristos node = hw_find_property (me, property); 5104e98e3e1Schristos if (node == NULL) 5114e98e3e1Schristos hw_abort (me, "property \"%s\" not found", property); 5124e98e3e1Schristos if (node->type != integer_property 5134e98e3e1Schristos && node->type != array_property) 5144e98e3e1Schristos hw_abort (me, "property \"%s\" of wrong type (integer or array)", property); 5154e98e3e1Schristos if ((node->sizeof_array % sizeof_integer) != 0) 5164e98e3e1Schristos hw_abort (me, "property \"%s\" contains an incomplete number of cells", property); 5174e98e3e1Schristos if (node->sizeof_array <= sizeof_integer * index) 5184e98e3e1Schristos return 0; 5194e98e3e1Schristos 5204e98e3e1Schristos /* Find and convert the value */ 5214e98e3e1Schristos cell = ((signed_cell*)node->array) + index; 5224e98e3e1Schristos *integer = BE2H_cell (*cell); 5234e98e3e1Schristos 5244e98e3e1Schristos return node->sizeof_array / sizeof_integer; 5254e98e3e1Schristos } 5264e98e3e1Schristos 5274e98e3e1Schristos 5284e98e3e1Schristos static unsigned_cell * 5294e98e3e1Schristos unit_address_to_cells (const hw_unit *unit, 5304e98e3e1Schristos unsigned_cell *cell, 5314e98e3e1Schristos int nr_cells) 5324e98e3e1Schristos { 5334e98e3e1Schristos int i; 5344e98e3e1Schristos ASSERT (nr_cells == unit->nr_cells); 5354e98e3e1Schristos for (i = 0; i < unit->nr_cells; i++) 5364e98e3e1Schristos { 5374e98e3e1Schristos *cell = H2BE_cell (unit->cells[i]); 5384e98e3e1Schristos cell += 1; 5394e98e3e1Schristos } 5404e98e3e1Schristos return cell; 5414e98e3e1Schristos } 5424e98e3e1Schristos 5434e98e3e1Schristos 5444e98e3e1Schristos static const unsigned_cell * 5454e98e3e1Schristos cells_to_unit_address (const unsigned_cell *cell, 5464e98e3e1Schristos hw_unit *unit, 5474e98e3e1Schristos int nr_cells) 5484e98e3e1Schristos { 5494e98e3e1Schristos int i; 5504e98e3e1Schristos memset (unit, 0, sizeof (*unit)); 5514e98e3e1Schristos unit->nr_cells = nr_cells; 5524e98e3e1Schristos for (i = 0; i < unit->nr_cells; i++) 5534e98e3e1Schristos { 5544e98e3e1Schristos unit->cells[i] = BE2H_cell (*cell); 5554e98e3e1Schristos cell += 1; 5564e98e3e1Schristos } 5574e98e3e1Schristos return cell; 5584e98e3e1Schristos } 5594e98e3e1Schristos 5604e98e3e1Schristos 5614e98e3e1Schristos static unsigned 5624e98e3e1Schristos nr_range_property_cells (struct hw *me, 5634e98e3e1Schristos int nr_ranges) 5644e98e3e1Schristos { 5654e98e3e1Schristos return ((hw_unit_nr_address_cells (me) 5664e98e3e1Schristos + hw_unit_nr_address_cells (hw_parent (me)) 5674e98e3e1Schristos + hw_unit_nr_size_cells (me)) 5684e98e3e1Schristos ) * nr_ranges; 5694e98e3e1Schristos } 5704e98e3e1Schristos 5714e98e3e1Schristos void 5724e98e3e1Schristos hw_add_range_array_property (struct hw *me, 5734e98e3e1Schristos const char *property, 5744e98e3e1Schristos const range_property_spec *ranges, 5754e98e3e1Schristos unsigned nr_ranges) 5764e98e3e1Schristos { 5774e98e3e1Schristos unsigned sizeof_cells = (nr_range_property_cells (me, nr_ranges) 5784e98e3e1Schristos * sizeof (unsigned_cell)); 5794e98e3e1Schristos unsigned_cell *cells = hw_zalloc (me, sizeof_cells); 5804e98e3e1Schristos unsigned_cell *cell; 5814e98e3e1Schristos int i; 5824e98e3e1Schristos 5834e98e3e1Schristos /* copy the property elements over */ 5844e98e3e1Schristos cell = cells; 5854e98e3e1Schristos for (i = 0; i < nr_ranges; i++) 5864e98e3e1Schristos { 5874e98e3e1Schristos const range_property_spec *range = &ranges[i]; 5884e98e3e1Schristos /* copy the child address */ 5894e98e3e1Schristos cell = unit_address_to_cells (&range->child_address, cell, 5904e98e3e1Schristos hw_unit_nr_address_cells (me)); 5914e98e3e1Schristos /* copy the parent address */ 5924e98e3e1Schristos cell = unit_address_to_cells (&range->parent_address, cell, 5934e98e3e1Schristos hw_unit_nr_address_cells (hw_parent (me))); 5944e98e3e1Schristos /* copy the size */ 5954e98e3e1Schristos cell = unit_address_to_cells (&range->size, cell, 5964e98e3e1Schristos hw_unit_nr_size_cells (me)); 5974e98e3e1Schristos } 5984e98e3e1Schristos ASSERT (cell == &cells[nr_range_property_cells (me, nr_ranges)]); 5994e98e3e1Schristos 6004e98e3e1Schristos /* add it */ 6014e98e3e1Schristos hw_add_property (me, property, range_array_property, 6024e98e3e1Schristos cells, sizeof_cells, 6034e98e3e1Schristos cells, sizeof_cells, 604*88241920Schristos NULL, permanent_object); 6054e98e3e1Schristos 6064e98e3e1Schristos hw_free (me, cells); 6074e98e3e1Schristos } 6084e98e3e1Schristos 6094e98e3e1Schristos int 6104e98e3e1Schristos hw_find_range_array_property (struct hw *me, 6114e98e3e1Schristos const char *property, 6124e98e3e1Schristos unsigned index, 6134e98e3e1Schristos range_property_spec *range) 6144e98e3e1Schristos { 6154e98e3e1Schristos const struct hw_property *node; 6164e98e3e1Schristos unsigned sizeof_entry = (nr_range_property_cells (me, 1) 6174e98e3e1Schristos * sizeof (unsigned_cell)); 6184e98e3e1Schristos const unsigned_cell *cells; 6194e98e3e1Schristos 6204e98e3e1Schristos /* locate the property */ 6214e98e3e1Schristos node = hw_find_property (me, property); 6224e98e3e1Schristos if (node == NULL) 6234e98e3e1Schristos hw_abort (me, "property \"%s\" not found", property); 6244e98e3e1Schristos if (node->type != range_array_property) 6254e98e3e1Schristos hw_abort (me, "property \"%s\" of wrong type (range array)", property); 6264e98e3e1Schristos 6274e98e3e1Schristos /* aligned ? */ 6284e98e3e1Schristos if ((node->sizeof_array % sizeof_entry) != 0) 6294e98e3e1Schristos hw_abort (me, "property \"%s\" contains an incomplete number of entries", 6304e98e3e1Schristos property); 6314e98e3e1Schristos 6324e98e3e1Schristos /* within bounds? */ 6334e98e3e1Schristos if (node->sizeof_array < sizeof_entry * (index + 1)) 6344e98e3e1Schristos return 0; 6354e98e3e1Schristos 6364e98e3e1Schristos /* find the range of interest */ 6374e98e3e1Schristos cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index); 6384e98e3e1Schristos 6394e98e3e1Schristos /* copy the child address out - converting as we go */ 6404e98e3e1Schristos cells = cells_to_unit_address (cells, &range->child_address, 6414e98e3e1Schristos hw_unit_nr_address_cells (me)); 6424e98e3e1Schristos 6434e98e3e1Schristos /* copy the parent address out - converting as we go */ 6444e98e3e1Schristos cells = cells_to_unit_address (cells, &range->parent_address, 6454e98e3e1Schristos hw_unit_nr_address_cells (hw_parent (me))); 6464e98e3e1Schristos 6474e98e3e1Schristos /* copy the size - converting as we go */ 6484e98e3e1Schristos cells = cells_to_unit_address (cells, &range->size, 6494e98e3e1Schristos hw_unit_nr_size_cells (me)); 6504e98e3e1Schristos 6514e98e3e1Schristos return node->sizeof_array / sizeof_entry; 6524e98e3e1Schristos } 6534e98e3e1Schristos 6544e98e3e1Schristos 6554e98e3e1Schristos static unsigned 6564e98e3e1Schristos nr_reg_property_cells (struct hw *me, 6574e98e3e1Schristos int nr_regs) 6584e98e3e1Schristos { 6594e98e3e1Schristos return (hw_unit_nr_address_cells (hw_parent (me)) 6604e98e3e1Schristos + hw_unit_nr_size_cells (hw_parent (me)) 6614e98e3e1Schristos ) * nr_regs; 6624e98e3e1Schristos } 6634e98e3e1Schristos 6644e98e3e1Schristos void 6654e98e3e1Schristos hw_add_reg_array_property (struct hw *me, 6664e98e3e1Schristos const char *property, 6674e98e3e1Schristos const reg_property_spec *regs, 6684e98e3e1Schristos unsigned nr_regs) 6694e98e3e1Schristos { 6704e98e3e1Schristos unsigned sizeof_cells = (nr_reg_property_cells (me, nr_regs) 6714e98e3e1Schristos * sizeof (unsigned_cell)); 6724e98e3e1Schristos unsigned_cell *cells = hw_zalloc (me, sizeof_cells); 6734e98e3e1Schristos unsigned_cell *cell; 6744e98e3e1Schristos int i; 6754e98e3e1Schristos 6764e98e3e1Schristos /* copy the property elements over */ 6774e98e3e1Schristos cell = cells; 6784e98e3e1Schristos for (i = 0; i < nr_regs; i++) 6794e98e3e1Schristos { 6804e98e3e1Schristos const reg_property_spec *reg = ®s[i]; 6814e98e3e1Schristos /* copy the address */ 6824e98e3e1Schristos cell = unit_address_to_cells (®->address, cell, 6834e98e3e1Schristos hw_unit_nr_address_cells (hw_parent (me))); 6844e98e3e1Schristos /* copy the size */ 6854e98e3e1Schristos cell = unit_address_to_cells (®->size, cell, 6864e98e3e1Schristos hw_unit_nr_size_cells (hw_parent (me))); 6874e98e3e1Schristos } 6884e98e3e1Schristos ASSERT (cell == &cells[nr_reg_property_cells (me, nr_regs)]); 6894e98e3e1Schristos 6904e98e3e1Schristos /* add it */ 6914e98e3e1Schristos hw_add_property (me, property, reg_array_property, 6924e98e3e1Schristos cells, sizeof_cells, 6934e98e3e1Schristos cells, sizeof_cells, 694*88241920Schristos NULL, permanent_object); 6954e98e3e1Schristos 6964e98e3e1Schristos hw_free (me, cells); 6974e98e3e1Schristos } 6984e98e3e1Schristos 6994e98e3e1Schristos int 7004e98e3e1Schristos hw_find_reg_array_property (struct hw *me, 7014e98e3e1Schristos const char *property, 7024e98e3e1Schristos unsigned index, 7034e98e3e1Schristos reg_property_spec *reg) 7044e98e3e1Schristos { 7054e98e3e1Schristos const struct hw_property *node; 7064e98e3e1Schristos unsigned sizeof_entry = (nr_reg_property_cells (me, 1) 7074e98e3e1Schristos * sizeof (unsigned_cell)); 7084e98e3e1Schristos const unsigned_cell *cells; 7094e98e3e1Schristos 7104e98e3e1Schristos /* locate the property */ 7114e98e3e1Schristos node = hw_find_property (me, property); 7124e98e3e1Schristos if (node == NULL) 7134e98e3e1Schristos hw_abort (me, "property \"%s\" not found", property); 7144e98e3e1Schristos if (node->type != reg_array_property) 7154e98e3e1Schristos hw_abort (me, "property \"%s\" of wrong type (reg array)", property); 7164e98e3e1Schristos 7174e98e3e1Schristos /* aligned ? */ 7184e98e3e1Schristos if ((node->sizeof_array % sizeof_entry) != 0) 7194e98e3e1Schristos hw_abort (me, "property \"%s\" contains an incomplete number of entries", 7204e98e3e1Schristos property); 7214e98e3e1Schristos 7224e98e3e1Schristos /* within bounds? */ 7234e98e3e1Schristos if (node->sizeof_array < sizeof_entry * (index + 1)) 7244e98e3e1Schristos return 0; 7254e98e3e1Schristos 7264e98e3e1Schristos /* find the range of interest */ 7274e98e3e1Schristos cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index); 7284e98e3e1Schristos 7294e98e3e1Schristos /* copy the address out - converting as we go */ 7304e98e3e1Schristos cells = cells_to_unit_address (cells, ®->address, 7314e98e3e1Schristos hw_unit_nr_address_cells (hw_parent (me))); 7324e98e3e1Schristos 7334e98e3e1Schristos /* copy the size out - converting as we go */ 7344e98e3e1Schristos cells = cells_to_unit_address (cells, ®->size, 7354e98e3e1Schristos hw_unit_nr_size_cells (hw_parent (me))); 7364e98e3e1Schristos 7374e98e3e1Schristos return node->sizeof_array / sizeof_entry; 7384e98e3e1Schristos } 7394e98e3e1Schristos 7404e98e3e1Schristos 7414e98e3e1Schristos void 7424e98e3e1Schristos hw_add_string_property (struct hw *me, 7434e98e3e1Schristos const char *property, 7444e98e3e1Schristos const char *string) 7454e98e3e1Schristos { 7464e98e3e1Schristos hw_add_property (me, property, string_property, 7474e98e3e1Schristos string, strlen (string) + 1, 7484e98e3e1Schristos string, strlen (string) + 1, 749*88241920Schristos NULL, permanent_object); 7504e98e3e1Schristos } 7514e98e3e1Schristos 7524e98e3e1Schristos const char * 7534e98e3e1Schristos hw_find_string_property (struct hw *me, 7544e98e3e1Schristos const char *property) 7554e98e3e1Schristos { 7564e98e3e1Schristos const struct hw_property *node; 7574e98e3e1Schristos const char *string; 7584e98e3e1Schristos node = hw_find_property (me, property); 7594e98e3e1Schristos if (node == NULL) 7604e98e3e1Schristos hw_abort (me, "property \"%s\" not found", property); 7614e98e3e1Schristos if (node->type != string_property) 7624e98e3e1Schristos hw_abort (me, "property \"%s\" of wrong type (string)", property); 7634e98e3e1Schristos string = node->array; 7644e98e3e1Schristos ASSERT (strlen (string) + 1 == node->sizeof_array); 7654e98e3e1Schristos return string; 7664e98e3e1Schristos } 7674e98e3e1Schristos 7684e98e3e1Schristos void 7694e98e3e1Schristos hw_add_string_array_property (struct hw *me, 7704e98e3e1Schristos const char *property, 7714e98e3e1Schristos const string_property_spec *strings, 7724e98e3e1Schristos unsigned nr_strings) 7734e98e3e1Schristos { 7744e98e3e1Schristos int sizeof_array; 7754e98e3e1Schristos int string_nr; 7764e98e3e1Schristos char *array; 7774e98e3e1Schristos char *chp; 7784e98e3e1Schristos if (nr_strings == 0) 7794e98e3e1Schristos hw_abort (me, "property \"%s\" must be non-null", property); 7804e98e3e1Schristos /* total up the size of the needed array */ 7814e98e3e1Schristos for (sizeof_array = 0, string_nr = 0; 7824e98e3e1Schristos string_nr < nr_strings; 7834e98e3e1Schristos string_nr ++) 7844e98e3e1Schristos { 7854e98e3e1Schristos sizeof_array += strlen (strings[string_nr]) + 1; 7864e98e3e1Schristos } 7874e98e3e1Schristos /* create the array */ 7884e98e3e1Schristos array = (char*) hw_zalloc (me, sizeof_array); 7894e98e3e1Schristos chp = array; 7904e98e3e1Schristos for (string_nr = 0; 7914e98e3e1Schristos string_nr < nr_strings; 7924e98e3e1Schristos string_nr++) 7934e98e3e1Schristos { 7944e98e3e1Schristos strcpy (chp, strings[string_nr]); 7954e98e3e1Schristos chp += strlen (chp) + 1; 7964e98e3e1Schristos } 7974e98e3e1Schristos ASSERT (chp == array + sizeof_array); 7984e98e3e1Schristos /* now enter it */ 7994e98e3e1Schristos hw_add_property (me, property, string_array_property, 8004e98e3e1Schristos array, sizeof_array, 8014e98e3e1Schristos array, sizeof_array, 802*88241920Schristos NULL, permanent_object); 8034e98e3e1Schristos } 8044e98e3e1Schristos 8054e98e3e1Schristos int 8064e98e3e1Schristos hw_find_string_array_property (struct hw *me, 8074e98e3e1Schristos const char *property, 8084e98e3e1Schristos unsigned index, 8094e98e3e1Schristos string_property_spec *string) 8104e98e3e1Schristos { 8114e98e3e1Schristos const struct hw_property *node; 8124e98e3e1Schristos node = hw_find_property (me, property); 8134e98e3e1Schristos if (node == NULL) 8144e98e3e1Schristos hw_abort (me, "property \"%s\" not found", property); 8154e98e3e1Schristos switch (node->type) 8164e98e3e1Schristos { 8174e98e3e1Schristos default: 8184e98e3e1Schristos hw_abort (me, "property \"%s\" of wrong type", property); 8194e98e3e1Schristos break; 8204e98e3e1Schristos case string_property: 8214e98e3e1Schristos if (index == 0) 8224e98e3e1Schristos { 8234e98e3e1Schristos *string = node->array; 8244e98e3e1Schristos ASSERT (strlen (*string) + 1 == node->sizeof_array); 8254e98e3e1Schristos return 1; 8264e98e3e1Schristos } 8274e98e3e1Schristos break; 8284e98e3e1Schristos case array_property: 8294e98e3e1Schristos if (node->sizeof_array == 0 8304e98e3e1Schristos || ((char*)node->array)[node->sizeof_array - 1] != '\0') 8314e98e3e1Schristos hw_abort (me, "property \"%s\" invalid for string array", property); 832*88241920Schristos ATTRIBUTE_FALLTHROUGH; 8334e98e3e1Schristos case string_array_property: 8344e98e3e1Schristos ASSERT (node->sizeof_array > 0); 8354e98e3e1Schristos ASSERT (((char*)node->array)[node->sizeof_array - 1] == '\0'); 8364e98e3e1Schristos { 8374e98e3e1Schristos const char *chp = node->array; 8384e98e3e1Schristos int nr_entries = 0; 8394e98e3e1Schristos /* count the number of strings, keeping an eye out for the one 8404e98e3e1Schristos we're looking for */ 8414e98e3e1Schristos *string = chp; 8424e98e3e1Schristos do 8434e98e3e1Schristos { 8444e98e3e1Schristos if (*chp == '\0') 8454e98e3e1Schristos { 8464e98e3e1Schristos /* next string */ 8474e98e3e1Schristos nr_entries++; 8484e98e3e1Schristos chp++; 8494e98e3e1Schristos if (nr_entries == index) 8504e98e3e1Schristos *string = chp; 8514e98e3e1Schristos } 8524e98e3e1Schristos else 8534e98e3e1Schristos { 8544e98e3e1Schristos chp++; 8554e98e3e1Schristos } 8564e98e3e1Schristos } while (chp < (char*)node->array + node->sizeof_array); 8574e98e3e1Schristos if (index < nr_entries) 8584e98e3e1Schristos return nr_entries; 8594e98e3e1Schristos else 8604e98e3e1Schristos { 8614e98e3e1Schristos *string = NULL; 8624e98e3e1Schristos return 0; 8634e98e3e1Schristos } 8644e98e3e1Schristos } 8654e98e3e1Schristos break; 8664e98e3e1Schristos } 8674e98e3e1Schristos return 0; 8684e98e3e1Schristos } 8694e98e3e1Schristos 8704e98e3e1Schristos void 8714e98e3e1Schristos hw_add_duplicate_property (struct hw *me, 8724e98e3e1Schristos const char *property, 8734e98e3e1Schristos const struct hw_property *original) 8744e98e3e1Schristos { 8754e98e3e1Schristos struct hw_property_data *master; 876*88241920Schristos if (original->disposition != permanent_object) 877*88241920Schristos hw_abort (me, "Can only duplicate permanent objects"); 8784e98e3e1Schristos /* find the original's master */ 8794e98e3e1Schristos master = original->owner->properties_of_hw; 8804e98e3e1Schristos while (master->property != original) 8814e98e3e1Schristos { 8824e98e3e1Schristos master = master->next; 8834e98e3e1Schristos ASSERT (master != NULL); 8844e98e3e1Schristos } 8854e98e3e1Schristos /* now duplicate it */ 8864e98e3e1Schristos hw_add_property (me, property, 8874e98e3e1Schristos original->type, 8884e98e3e1Schristos master->init_array, master->sizeof_init_array, 8894e98e3e1Schristos original->array, original->sizeof_array, 890*88241920Schristos original, permanent_object); 8914e98e3e1Schristos } 892