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