1193323Sed/* The common simulator framework for GDB, the GNU Debugger. 2193323Sed 3193323Sed Copyright 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. 4193323Sed 5193323Sed Contributed by Andrew Cagney and Red Hat. 6193323Sed 7193323Sed This file is part of GDB. 8193323Sed 9193323Sed This program is free software; you can redistribute it and/or modify 10193323Sed it under the terms of the GNU General Public License as published by 11193323Sed the Free Software Foundation; either version 3 of the License, or 12193323Sed (at your option) any later version. 13193323Sed 14193323Sed This program is distributed in the hope that it will be useful, 15193323Sed but WITHOUT ANY WARRANTY; without even the implied warranty of 16193323Sed MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17239462Sdim GNU General Public License for more details. 18234353Sdim 19193323Sed You should have received a copy of the GNU General Public License 20193323Sed along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21193323Sed 22193323Sed#include "hw-main.h" 23218893Sdim#include "hw-base.h" 24193323Sed 25193323Sed#include "sim-io.h" 26193323Sed#include "sim-assert.h" 27193323Sed 28193323Sed#ifdef HAVE_STRING_H 29193323Sed#include <string.h> 30193323Sed#else 31193323Sed#ifdef HAVE_STRINGS_H 32193323Sed#include <strings.h> 33193323Sed#endif 34193323Sed#endif 35193323Sed 36193323Sed/* property entries */ 37193323Sed 38193323Sedstruct hw_property_data 39193323Sed{ 40193323Sed struct hw_property_data *next; 41193323Sed struct hw_property *property; 42193323Sed const void *init_array; 43193323Sed unsigned sizeof_init_array; 44193323Sed}; 45193323Sed 46193323Sedvoid 47193323Sedcreate_hw_property_data (struct hw *me) 48193323Sed{ 49193323Sed} 50193323Sed 51193323Sedvoid 52193323Seddelete_hw_property_data (struct hw *me) 53193323Sed{ 54207618Srdivacky} 55207618Srdivacky 56207618Srdivacky 57207618Srdivacky/* Device Properties: */ 58207618Srdivacky 59193323Sedstatic struct hw_property_data * 60193323Sedfind_property_data (struct hw *me, 61193323Sed const char *property) 62193323Sed{ 63193323Sed struct hw_property_data *entry; 64193323Sed ASSERT (property != NULL); 65193323Sed entry = me->properties_of_hw; 66193323Sed while (entry != NULL) 67193323Sed { 68193323Sed if (strcmp (entry->property->name, property) == 0) 69193323Sed return entry; 70193323Sed entry = entry->next; 71193323Sed } 72193323Sed return NULL; 73193323Sed} 74193323Sed 75193323Sed 76193323Sedstatic void 77193323Sedhw_add_property (struct hw *me, 78193323Sed const char *property, 79193323Sed hw_property_type type, 80193323Sed const void *init_array, 81193323Sed unsigned sizeof_init_array, 82218893Sdim const void *array, 83193323Sed unsigned sizeof_array, 84193323Sed const struct hw_property *original, 85193323Sed object_disposition disposition) 86193323Sed{ 87193323Sed struct hw_property_data *new_entry = NULL; 88193323Sed struct hw_property *new_value = NULL; 89193323Sed 90193323Sed /* find the list end */ 91193323Sed struct hw_property_data **insertion_point = &me->properties_of_hw; 92193323Sed while (*insertion_point != NULL) 93193323Sed { 94193323Sed if (strcmp ((*insertion_point)->property->name, property) == 0) 95193323Sed return; 96193323Sed insertion_point = &(*insertion_point)->next; 97218893Sdim } 98218893Sdim 99193323Sed /* create a new value */ 100193323Sed new_value = HW_ZALLOC (me, struct hw_property); 101249423Sdim new_value->name = (char *) strdup (property); 102239462Sdim new_value->type = type; 103239462Sdim if (sizeof_array > 0) 104239462Sdim { 105239462Sdim void *new_array = hw_zalloc (me, sizeof_array); 106239462Sdim memcpy (new_array, array, sizeof_array); 107239462Sdim new_value->array = new_array; 108193323Sed new_value->sizeof_array = sizeof_array; 109218893Sdim } 110193323Sed new_value->owner = me; 111193323Sed new_value->original = original; 112202375Srdivacky new_value->disposition = disposition; 113202375Srdivacky 114202375Srdivacky /* insert the value into the list */ 115193323Sed new_entry = HW_ZALLOC (me, struct hw_property_data); 116193323Sed *insertion_point = new_entry; 117193323Sed if (sizeof_init_array > 0) 118193323Sed { 119193323Sed void *new_init_array = hw_zalloc (me, sizeof_init_array); 120193323Sed memcpy (new_init_array, init_array, sizeof_init_array); 121193323Sed new_entry->init_array = new_init_array; 122193323Sed new_entry->sizeof_init_array = sizeof_init_array; 123193323Sed } 124193323Sed new_entry->property = new_value; 125193323Sed} 126193323Sed 127234353Sdim 128193323Sedstatic void 129193323Sedhw_set_property (struct hw *me, 130193323Sed const char *property, 131193323Sed hw_property_type type, 132193323Sed const void *array, 133193323Sed int sizeof_array) 134193323Sed{ 135193323Sed /* find the property */ 136193323Sed struct hw_property_data *entry = find_property_data (me, property); 137193323Sed if (entry != NULL) 138193323Sed { 139218893Sdim /* existing property - update it */ 140218893Sdim void *new_array = 0; 141218893Sdim struct hw_property *value = entry->property; 142218893Sdim /* check the type matches */ 143218893Sdim if (value->type != type) 144218893Sdim hw_abort (me, "conflict between type of new and old value for property %s", property); 145193323Sed /* replace its value */ 146193323Sed if (value->array != NULL) 147193323Sed hw_free (me, (void*)value->array); 148193323Sed new_array = (sizeof_array > 0 149193323Sed ? hw_zalloc (me, sizeof_array) 150193323Sed : (void*)0); 151193323Sed value->array = new_array; 152193323Sed value->sizeof_array = sizeof_array; 153193323Sed if (sizeof_array > 0) 154193323Sed memcpy (new_array, array, sizeof_array); 155193323Sed return; 156193323Sed } 157234353Sdim else 158193323Sed { 159234353Sdim /* new property - create it */ 160193323Sed hw_add_property (me, property, type, 161193323Sed NULL, 0, array, sizeof_array, 162193323Sed NULL, temporary_object); 163193323Sed } 164193323Sed} 165193323Sed 166193323Sed 167193323Sed#if 0 168193323Sedstatic void 169193323Sedclean_hw_properties (struct hw *me) 170193323Sed{ 171193323Sed struct hw_property_data **delete_point = &me->properties_of_hw; 172193323Sed while (*delete_point != NULL) 173193323Sed { 174193323Sed struct hw_property_data *current = *delete_point; 175243830Sdim switch (current->property->disposition) 176193323Sed { 177193323Sed case permenant_object: 178193323Sed /* zap the current value, will be initialized later */ 179193323Sed ASSERT (current->init_array != NULL); 180234353Sdim if (current->property->array != NULL) 181193323Sed { 182234353Sdim hw_free (me, (void*)current->property->array); 183193323Sed current->property->array = NULL; 184193323Sed } 185193323Sed delete_point = &(*delete_point)->next; 186193323Sed break; 187193323Sed case temporary_object: 188193323Sed /* zap the actual property, was created during simulation run */ 189193323Sed ASSERT (current->init_array == NULL); 190234353Sdim *delete_point = current->next; 191193323Sed if (current->property->array != NULL) 192234353Sdim hw_free (me, (void*)current->property->array); 193193323Sed hw_free (me, current->property); 194193323Sed hw_free (me, current); 195193323Sed break; 196193323Sed } 197193323Sed } 198193323Sed} 199193323Sed#endif 200193323Sed 201193323Sed#if 0 202193323Sedvoid 203193323Sedhw_init_static_properties (SIM_DESC sd, 204193323Sed struct hw *me, 205193323Sed void *data) 206193323Sed{ 207193323Sed struct hw_property_data *property; 208193323Sed for (property = me->properties_of_hw; 209193323Sed property != NULL; 210193323Sed property = property->next) 211193323Sed { 212193323Sed ASSERT (property->init_array != NULL); 213193323Sed ASSERT (property->property->array == NULL); 214193323Sed ASSERT(property->property->disposition == permenant_object); 215193323Sed switch (property->property->type) 216193323Sed { 217193323Sed case array_property: 218193323Sed case boolean_property: 219193323Sed case range_array_property: 220193323Sed case reg_array_property: 221193323Sed case string_property: 222193323Sed case string_array_property: 223193323Sed case integer_property: 224193323Sed /* delete the property, and replace it with the original */ 225193323Sed hw_set_property (me, property->property->name, 226193323Sed property->property->type, 227193323Sed property->init_array, 228193323Sed property->sizeof_init_array); 229193323Sed break; 230193323Sed#if 0 231193323Sed case ihandle_property: 232193323Sed break; 233193323Sed#endif 234193323Sed } 235193323Sed } 236193323Sed} 237193323Sed#endif 238193323Sed 239193323Sed 240243830Sdim#if 0 241243830Sdimvoid 242243830Sdimhw_init_runtime_properties (SIM_DESC sd, 243243830Sdim struct hw *me, 244243830Sdim void *data) 245243830Sdim{ 246243830Sdim struct hw_property_data *property; 247243830Sdim for (property = me->properties_of_hw; 248243830Sdim property != NULL; 249243830Sdim property = property->next) 250243830Sdim { 251243830Sdim switch (property->property->disposition) 252243830Sdim { 253243830Sdim case permenant_object: 254243830Sdim switch (property->property->type) 255243830Sdim { 256243830Sdim#if 0 257243830Sdim case ihandle_property: 258243830Sdim { 259243830Sdim struct hw_instance *ihandle; 260243830Sdim ihandle_runtime_property_spec spec; 261243830Sdim ASSERT (property->init_array != NULL); 262243830Sdim ASSERT (property->property->array == NULL); 263243830Sdim hw_find_ihandle_runtime_property (me, property->property->name, &spec); 264243830Sdim ihandle = tree_instance (me, spec.full_path); 265243830Sdim hw_set_ihandle_property (me, property->property->name, ihandle); 266243830Sdim break; 267243830Sdim } 268193323Sed#endif 269193323Sed case array_property: 270193323Sed case boolean_property: 271193323Sed case range_array_property: 272193323Sed case integer_property: 273193323Sed case reg_array_property: 274193323Sed case string_property: 275193323Sed case string_array_property: 276193323Sed ASSERT (property->init_array != NULL); 277193323Sed ASSERT (property->property->array != NULL); 278243830Sdim break; 279243830Sdim } 280243830Sdim break; 281243830Sdim case temporary_object: 282243830Sdim ASSERT (property->init_array == NULL); 283243830Sdim ASSERT (property->property->array != NULL); 284243830Sdim break; 285243830Sdim } 286243830Sdim } 287243830Sdim} 288243830Sdim#endif 289243830Sdim 290243830Sdim 291243830Sdim 292243830Sdimconst struct hw_property * 293243830Sdimhw_next_property (const struct hw_property *property) 294243830Sdim{ 295243830Sdim /* find the property in the list */ 296243830Sdim struct hw *owner = property->owner; 297243830Sdim struct hw_property_data *entry = owner->properties_of_hw; 298243830Sdim while (entry != NULL && entry->property != property) 299243830Sdim entry = entry->next; 300243830Sdim /* now return the following property */ 301243830Sdim ASSERT (entry != NULL); /* must be a member! */ 302243830Sdim if (entry->next != NULL) 303243830Sdim return entry->next->property; 304243830Sdim else 305243830Sdim return NULL; 306193323Sed} 307193323Sed 308193323Sed 309193323Sedconst struct hw_property * 310193323Sedhw_find_property (struct hw *me, 311193323Sed const char *property) 312193323Sed{ 313193323Sed if (me == NULL) 314193323Sed { 315193323Sed return NULL; 316193323Sed } 317193323Sed else if (property == NULL || strcmp (property, "") == 0) 318193323Sed { 319193323Sed if (me->properties_of_hw == NULL) 320193323Sed return NULL; 321193323Sed else 322193323Sed return me->properties_of_hw->property; 323193323Sed } 324193323Sed else 325193323Sed { 326193323Sed struct hw_property_data *entry = find_property_data (me, property); 327193323Sed if (entry != NULL) 328193323Sed return entry->property; 329193323Sed } 330193323Sed return NULL; 331193323Sed} 332193323Sed 333193323Sed 334239462Sdimvoid 335239462Sdimhw_add_array_property (struct hw *me, 336239462Sdim const char *property, 337239462Sdim const void *array, 338239462Sdim int sizeof_array) 339239462Sdim{ 340239462Sdim hw_add_property (me, property, array_property, 341239462Sdim array, sizeof_array, array, sizeof_array, 342239462Sdim NULL, permenant_object); 343239462Sdim} 344193323Sed 345193323Sedvoid 346193323Sedhw_set_array_property (struct hw *me, 347193323Sed const char *property, 348193323Sed const void *array, 349193323Sed int sizeof_array) 350193323Sed{ 351193323Sed hw_set_property (me, property, array_property, array, sizeof_array); 352193323Sed} 353193323Sed 354193323Sedconst struct hw_property * 355193323Sedhw_find_array_property (struct hw *me, 356193323Sed const char *property) 357193323Sed{ 358193323Sed const struct hw_property *node; 359193323Sed node = hw_find_property (me, property); 360193323Sed if (node == NULL) 361193323Sed hw_abort (me, "property \"%s\" not found", property); 362193323Sed if (node->type != array_property) 363193323Sed hw_abort (me, "property \"%s\" of wrong type (array)", property); 364193323Sed return node; 365193323Sed} 366193323Sed 367193323Sed 368193323Sed 369193323Sedvoid 370243830Sdimhw_add_boolean_property (struct hw *me, 371193323Sed const char *property, 372193323Sed int boolean) 373193323Sed{ 374193323Sed signed32 new_boolean = (boolean ? -1 : 0); 375193323Sed hw_add_property (me, property, boolean_property, 376193323Sed &new_boolean, sizeof(new_boolean), 377193323Sed &new_boolean, sizeof(new_boolean), 378193323Sed NULL, permenant_object); 379193323Sed} 380193323Sed 381193323Sedint 382193323Sedhw_find_boolean_property (struct hw *me, 383193323Sed const char *property) 384193323Sed{ 385193323Sed const struct hw_property *node; 386193323Sed unsigned_cell boolean; 387243830Sdim node = hw_find_property (me, property); 388234353Sdim if (node == NULL) 389234353Sdim hw_abort (me, "property \"%s\" not found", property); 390234353Sdim if (node->type != boolean_property) 391234353Sdim hw_abort (me, "property \"%s\" of wrong type (boolean)", property); 392234353Sdim ASSERT (sizeof (boolean) == node->sizeof_array); 393234353Sdim memcpy (&boolean, node->array, sizeof (boolean)); 394234353Sdim return boolean; 395234353Sdim} 396234353Sdim 397243830Sdim 398243830Sdim 399243830Sdim#if 0 400243830Sdimvoid 401243830Sdimhw_add_ihandle_runtime_property (struct hw *me, 402243830Sdim const char *property, 403243830Sdim const ihandle_runtime_property_spec *ihandle) 404243830Sdim{ 405243830Sdim /* enter the full path as the init array */ 406243830Sdim hw_add_property (me, property, ihandle_property, 407243830Sdim ihandle->full_path, strlen(ihandle->full_path) + 1, 408243830Sdim NULL, 0, 409243830Sdim NULL, permenant_object); 410243830Sdim} 411243830Sdim#endif 412243830Sdim 413243830Sdim#if 0 414193323Sedvoid 415203954Srdivackyhw_find_ihandle_runtime_property (struct hw *me, 416203954Srdivacky const char *property, 417203954Srdivacky ihandle_runtime_property_spec *ihandle) 418193323Sed{ 419193323Sed struct hw_property_data *entry = find_property_data (me, property); 420193323Sed HW_TRACE ((me, "hw_find_ihandle_runtime_property(property=%s)\n", property)); 421193323Sed if (entry == NULL) 422193323Sed hw_abort (me, "property \"%s\" not found", property); 423203954Srdivacky if (entry->property->type != ihandle_property 424203954Srdivacky || entry->property->disposition != permenant_object) 425203954Srdivacky hw_abort (me, "property \"%s\" of wrong type", property); 426193323Sed ASSERT (entry->init_array != NULL); 427193323Sed /* the full path */ 428193323Sed ihandle->full_path = entry->init_array; 429193323Sed} 430193323Sed#endif 431193323Sed 432193323Sed 433193323Sed 434193323Sed#if 0 435193323Sedvoid 436193323Sedhw_set_ihandle_property (struct hw *me, 437205407Srdivacky const char *property, 438218893Sdim hw_instance *ihandle) 439193323Sed{ 440193323Sed unsigned_cell cells; 441193323Sed cells = H2BE_cell (hw_instance_to_external (ihandle)); 442193323Sed hw_set_property (me, property, ihandle_property, 443193323Sed &cells, sizeof (cells)); 444193323Sed 445218893Sdim} 446218893Sdim#endif 447193323Sed 448193323Sed#if 0 449218893Sdimhw_instance * 450193323Sedhw_find_ihandle_property (struct hw *me, 451193323Sed const char *property) 452193323Sed{ 453193323Sed const hw_property_data *node; 454193323Sed unsigned_cell ihandle; 455249423Sdim hw_instance *instance; 456239462Sdim 457239462Sdim node = hw_find_property (me, property); 458239462Sdim if (node == NULL) 459239462Sdim hw_abort (me, "property \"%s\" not found", property); 460239462Sdim if (node->type != ihandle_property) 461239462Sdim hw_abort(me, "property \"%s\" of wrong type (ihandle)", property); 462239462Sdim if (node->array == NULL) 463239462Sdim hw_abort(me, "runtime property \"%s\" not yet initialized", property); 464239462Sdim 465239462Sdim ASSERT (sizeof(ihandle) == node->sizeof_array); 466239462Sdim memcpy (&ihandle, node->array, sizeof(ihandle)); 467239462Sdim instance = external_to_hw_instance (me, BE2H_cell(ihandle)); 468239462Sdim ASSERT (instance != NULL); 469239462Sdim return instance; 470202375Srdivacky} 471202375Srdivacky#endif 472202375Srdivacky 473202375Srdivacky 474202375Srdivackyvoid 475202375Srdivackyhw_add_integer_property (struct hw *me, 476234353Sdim const char *property, 477234353Sdim signed_cell integer) 478234353Sdim{ 479234353Sdim H2BE (integer); 480234353Sdim hw_add_property (me, property, integer_property, 481234353Sdim &integer, sizeof(integer), 482234353Sdim &integer, sizeof(integer), 483234353Sdim NULL, permenant_object); 484234353Sdim} 485234353Sdim 486234353Sdimsigned_cell 487234353Sdimhw_find_integer_property (struct hw *me, 488234353Sdim const char *property) 489234353Sdim{ 490234353Sdim const struct hw_property *node; 491234353Sdim signed_cell integer; 492234353Sdim HW_TRACE ((me, "hw_find_integer(property=%s)\n", property)); 493234353Sdim node = hw_find_property (me, property); 494234353Sdim if (node == NULL) 495234353Sdim hw_abort (me, "property \"%s\" not found", property); 496234353Sdim if (node->type != integer_property) 497234353Sdim hw_abort (me, "property \"%s\" of wrong type (integer)", property); 498234353Sdim ASSERT (sizeof(integer) == node->sizeof_array); 499234353Sdim memcpy (&integer, node->array, sizeof (integer)); 500234353Sdim return BE2H_cell (integer); 501234353Sdim} 502234353Sdim 503234353Sdimint 504234353Sdimhw_find_integer_array_property (struct hw *me, 505234353Sdim const char *property, 506234353Sdim unsigned index, 507234353Sdim signed_cell *integer) 508234353Sdim{ 509234353Sdim const struct hw_property *node; 510234353Sdim int sizeof_integer = sizeof (*integer); 511234353Sdim signed_cell *cell; 512193323Sed HW_TRACE ((me, "hw_find_integer(property=%s)\n", property)); 513193323Sed 514193323Sed /* check things sane */ 515193323Sed node = hw_find_property (me, property); 516193323Sed if (node == NULL) 517193323Sed hw_abort (me, "property \"%s\" not found", property); 518193323Sed if (node->type != integer_property 519193323Sed && node->type != array_property) 520193323Sed hw_abort (me, "property \"%s\" of wrong type (integer or array)", property); 521193323Sed if ((node->sizeof_array % sizeof_integer) != 0) 522193323Sed hw_abort (me, "property \"%s\" contains an incomplete number of cells", property); 523193323Sed if (node->sizeof_array <= sizeof_integer * index) 524193323Sed return 0; 525193323Sed 526193323Sed /* Find and convert the value */ 527243830Sdim cell = ((signed_cell*)node->array) + index; 528243830Sdim *integer = BE2H_cell (*cell); 529243830Sdim 530243830Sdim return node->sizeof_array / sizeof_integer; 531243830Sdim} 532193323Sed 533193323Sed 534193323Sedstatic unsigned_cell * 535193323Sedunit_address_to_cells (const hw_unit *unit, 536193323Sed unsigned_cell *cell, 537193323Sed int nr_cells) 538193323Sed{ 539193323Sed int i; 540193323Sed ASSERT(nr_cells == unit->nr_cells); 541218893Sdim for (i = 0; i < unit->nr_cells; i++) 542218893Sdim { 543193323Sed *cell = H2BE_cell (unit->cells[i]); 544193323Sed cell += 1; 545193323Sed } 546193323Sed return cell; 547193323Sed} 548193323Sed 549193323Sed 550234353Sdimstatic const unsigned_cell * 551234353Sdimcells_to_unit_address (const unsigned_cell *cell, 552234353Sdim hw_unit *unit, 553234353Sdim int nr_cells) 554234353Sdim{ 555234353Sdim int i; 556234353Sdim memset(unit, 0, sizeof(*unit)); 557234353Sdim unit->nr_cells = nr_cells; 558234353Sdim for (i = 0; i < unit->nr_cells; i++) 559234353Sdim { 560234353Sdim unit->cells[i] = BE2H_cell (*cell); 561234353Sdim cell += 1; 562234353Sdim } 563234353Sdim return cell; 564234353Sdim} 565234353Sdim 566234353Sdim 567234353Sdimstatic unsigned 568234353Sdimnr_range_property_cells (struct hw *me, 569234353Sdim int nr_ranges) 570234353Sdim{ 571234353Sdim return ((hw_unit_nr_address_cells (me) 572234353Sdim + hw_unit_nr_address_cells (hw_parent (me)) 573234353Sdim + hw_unit_nr_size_cells (me)) 574234353Sdim ) * nr_ranges; 575234353Sdim} 576234353Sdim 577193323Sedvoid 578193323Sedhw_add_range_array_property (struct hw *me, 579193323Sed const char *property, 580202375Srdivacky const range_property_spec *ranges, 581202375Srdivacky unsigned nr_ranges) 582202375Srdivacky{ 583202375Srdivacky unsigned sizeof_cells = (nr_range_property_cells (me, nr_ranges) 584202375Srdivacky * sizeof (unsigned_cell)); 585202375Srdivacky unsigned_cell *cells = hw_zalloc (me, sizeof_cells); 586202375Srdivacky unsigned_cell *cell; 587202375Srdivacky int i; 588202375Srdivacky 589193323Sed /* copy the property elements over */ 590 cell = cells; 591 for (i = 0; i < nr_ranges; i++) 592 { 593 const range_property_spec *range = &ranges[i]; 594 /* copy the child address */ 595 cell = unit_address_to_cells (&range->child_address, cell, 596 hw_unit_nr_address_cells (me)); 597 /* copy the parent address */ 598 cell = unit_address_to_cells (&range->parent_address, cell, 599 hw_unit_nr_address_cells (hw_parent (me))); 600 /* copy the size */ 601 cell = unit_address_to_cells (&range->size, cell, 602 hw_unit_nr_size_cells (me)); 603 } 604 ASSERT (cell == &cells[nr_range_property_cells (me, nr_ranges)]); 605 606 /* add it */ 607 hw_add_property (me, property, range_array_property, 608 cells, sizeof_cells, 609 cells, sizeof_cells, 610 NULL, permenant_object); 611 612 hw_free (me, cells); 613} 614 615int 616hw_find_range_array_property (struct hw *me, 617 const char *property, 618 unsigned index, 619 range_property_spec *range) 620{ 621 const struct hw_property *node; 622 unsigned sizeof_entry = (nr_range_property_cells (me, 1) 623 * sizeof (unsigned_cell)); 624 const unsigned_cell *cells; 625 626 /* locate the property */ 627 node = hw_find_property (me, property); 628 if (node == NULL) 629 hw_abort (me, "property \"%s\" not found", property); 630 if (node->type != range_array_property) 631 hw_abort (me, "property \"%s\" of wrong type (range array)", property); 632 633 /* aligned ? */ 634 if ((node->sizeof_array % sizeof_entry) != 0) 635 hw_abort (me, "property \"%s\" contains an incomplete number of entries", 636 property); 637 638 /* within bounds? */ 639 if (node->sizeof_array < sizeof_entry * (index + 1)) 640 return 0; 641 642 /* find the range of interest */ 643 cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index); 644 645 /* copy the child address out - converting as we go */ 646 cells = cells_to_unit_address (cells, &range->child_address, 647 hw_unit_nr_address_cells (me)); 648 649 /* copy the parent address out - converting as we go */ 650 cells = cells_to_unit_address (cells, &range->parent_address, 651 hw_unit_nr_address_cells (hw_parent (me))); 652 653 /* copy the size - converting as we go */ 654 cells = cells_to_unit_address (cells, &range->size, 655 hw_unit_nr_size_cells (me)); 656 657 return node->sizeof_array / sizeof_entry; 658} 659 660 661static unsigned 662nr_reg_property_cells (struct hw *me, 663 int nr_regs) 664{ 665 return (hw_unit_nr_address_cells (hw_parent(me)) 666 + hw_unit_nr_size_cells (hw_parent(me)) 667 ) * nr_regs; 668} 669 670void 671hw_add_reg_array_property (struct hw *me, 672 const char *property, 673 const reg_property_spec *regs, 674 unsigned nr_regs) 675{ 676 unsigned sizeof_cells = (nr_reg_property_cells (me, nr_regs) 677 * sizeof (unsigned_cell)); 678 unsigned_cell *cells = hw_zalloc (me, sizeof_cells); 679 unsigned_cell *cell; 680 int i; 681 682 /* copy the property elements over */ 683 cell = cells; 684 for (i = 0; i < nr_regs; i++) 685 { 686 const reg_property_spec *reg = ®s[i]; 687 /* copy the address */ 688 cell = unit_address_to_cells (®->address, cell, 689 hw_unit_nr_address_cells (hw_parent (me))); 690 /* copy the size */ 691 cell = unit_address_to_cells (®->size, cell, 692 hw_unit_nr_size_cells (hw_parent (me))); 693 } 694 ASSERT (cell == &cells[nr_reg_property_cells (me, nr_regs)]); 695 696 /* add it */ 697 hw_add_property (me, property, reg_array_property, 698 cells, sizeof_cells, 699 cells, sizeof_cells, 700 NULL, permenant_object); 701 702 hw_free (me, cells); 703} 704 705int 706hw_find_reg_array_property (struct hw *me, 707 const char *property, 708 unsigned index, 709 reg_property_spec *reg) 710{ 711 const struct hw_property *node; 712 unsigned sizeof_entry = (nr_reg_property_cells (me, 1) 713 * sizeof (unsigned_cell)); 714 const unsigned_cell *cells; 715 716 /* locate the property */ 717 node = hw_find_property (me, property); 718 if (node == NULL) 719 hw_abort (me, "property \"%s\" not found", property); 720 if (node->type != reg_array_property) 721 hw_abort (me, "property \"%s\" of wrong type (reg array)", property); 722 723 /* aligned ? */ 724 if ((node->sizeof_array % sizeof_entry) != 0) 725 hw_abort (me, "property \"%s\" contains an incomplete number of entries", 726 property); 727 728 /* within bounds? */ 729 if (node->sizeof_array < sizeof_entry * (index + 1)) 730 return 0; 731 732 /* find the range of interest */ 733 cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index); 734 735 /* copy the address out - converting as we go */ 736 cells = cells_to_unit_address (cells, ®->address, 737 hw_unit_nr_address_cells (hw_parent (me))); 738 739 /* copy the size out - converting as we go */ 740 cells = cells_to_unit_address (cells, ®->size, 741 hw_unit_nr_size_cells (hw_parent (me))); 742 743 return node->sizeof_array / sizeof_entry; 744} 745 746 747void 748hw_add_string_property (struct hw *me, 749 const char *property, 750 const char *string) 751{ 752 hw_add_property (me, property, string_property, 753 string, strlen(string) + 1, 754 string, strlen(string) + 1, 755 NULL, permenant_object); 756} 757 758const char * 759hw_find_string_property (struct hw *me, 760 const char *property) 761{ 762 const struct hw_property *node; 763 const char *string; 764 node = hw_find_property (me, property); 765 if (node == NULL) 766 hw_abort (me, "property \"%s\" not found", property); 767 if (node->type != string_property) 768 hw_abort (me, "property \"%s\" of wrong type (string)", property); 769 string = node->array; 770 ASSERT (strlen(string) + 1 == node->sizeof_array); 771 return string; 772} 773 774void 775hw_add_string_array_property (struct hw *me, 776 const char *property, 777 const string_property_spec *strings, 778 unsigned nr_strings) 779{ 780 int sizeof_array; 781 int string_nr; 782 char *array; 783 char *chp; 784 if (nr_strings == 0) 785 hw_abort (me, "property \"%s\" must be non-null", property); 786 /* total up the size of the needed array */ 787 for (sizeof_array = 0, string_nr = 0; 788 string_nr < nr_strings; 789 string_nr ++) 790 { 791 sizeof_array += strlen (strings[string_nr]) + 1; 792 } 793 /* create the array */ 794 array = (char*) hw_zalloc (me, sizeof_array); 795 chp = array; 796 for (string_nr = 0; 797 string_nr < nr_strings; 798 string_nr++) 799 { 800 strcpy (chp, strings[string_nr]); 801 chp += strlen (chp) + 1; 802 } 803 ASSERT (chp == array + sizeof_array); 804 /* now enter it */ 805 hw_add_property (me, property, string_array_property, 806 array, sizeof_array, 807 array, sizeof_array, 808 NULL, permenant_object); 809} 810 811int 812hw_find_string_array_property (struct hw *me, 813 const char *property, 814 unsigned index, 815 string_property_spec *string) 816{ 817 const struct hw_property *node; 818 node = hw_find_property (me, property); 819 if (node == NULL) 820 hw_abort (me, "property \"%s\" not found", property); 821 switch (node->type) 822 { 823 default: 824 hw_abort (me, "property \"%s\" of wrong type", property); 825 break; 826 case string_property: 827 if (index == 0) 828 { 829 *string = node->array; 830 ASSERT (strlen(*string) + 1 == node->sizeof_array); 831 return 1; 832 } 833 break; 834 case array_property: 835 if (node->sizeof_array == 0 836 || ((char*)node->array)[node->sizeof_array - 1] != '\0') 837 hw_abort (me, "property \"%s\" invalid for string array", property); 838 /* FALL THROUGH */ 839 case string_array_property: 840 ASSERT (node->sizeof_array > 0); 841 ASSERT (((char*)node->array)[node->sizeof_array - 1] == '\0'); 842 { 843 const char *chp = node->array; 844 int nr_entries = 0; 845 /* count the number of strings, keeping an eye out for the one 846 we're looking for */ 847 *string = chp; 848 do 849 { 850 if (*chp == '\0') 851 { 852 /* next string */ 853 nr_entries++; 854 chp++; 855 if (nr_entries == index) 856 *string = chp; 857 } 858 else 859 { 860 chp++; 861 } 862 } while (chp < (char*)node->array + node->sizeof_array); 863 if (index < nr_entries) 864 return nr_entries; 865 else 866 { 867 *string = NULL; 868 return 0; 869 } 870 } 871 break; 872 } 873 return 0; 874} 875 876void 877hw_add_duplicate_property (struct hw *me, 878 const char *property, 879 const struct hw_property *original) 880{ 881 struct hw_property_data *master; 882 HW_TRACE ((me, "hw_add_duplicate_property(property=%s, ...)\n", property)); 883 if (original->disposition != permenant_object) 884 hw_abort (me, "Can only duplicate permenant objects"); 885 /* find the original's master */ 886 master = original->owner->properties_of_hw; 887 while (master->property != original) 888 { 889 master = master->next; 890 ASSERT(master != NULL); 891 } 892 /* now duplicate it */ 893 hw_add_property (me, property, 894 original->type, 895 master->init_array, master->sizeof_init_array, 896 original->array, original->sizeof_array, 897 original, permenant_object); 898} 899