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 = ®s[i]; 681 1.1 christos /* copy the address */ 682 1.1 christos cell = unit_address_to_cells (®->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 (®->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, ®->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, ®->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