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