void hw_add_reg_array_property (struct hw *me, const char *property, const reg_property_spec *regs, unsigned nr_regs) { unsigned sizeof_cells = (nr_reg_property_cells (me, nr_regs) * sizeof (unsigned_cell)); unsigned_cell *cells = hw_zalloc (me, sizeof_cells); unsigned_cell *cell; int i; /* copy the property elements over */ cell = cells; for (i = 0; i < nr_regs; i++) { const reg_property_spec *reg = ®s[i]; /* copy the address */ cell = unit_address_to_cells (®->address, cell, hw_unit_nr_address_cells (hw_parent (me))); /* copy the size */ cell = unit_address_to_cells (®->size, cell, hw_unit_nr_size_cells (hw_parent (me))); } ASSERT (cell == &cells[nr_reg_property_cells (me, nr_regs)]); /* add it */ hw_add_property (me, property, reg_array_property, cells, sizeof_cells, cells, sizeof_cells, NULL, permenant_object); hw_free (me, cells); }
static unsigned nr_reg_property_cells (struct hw *me, int nr_regs) { return (hw_unit_nr_address_cells (hw_parent(me)) + hw_unit_nr_size_cells (hw_parent(me)) ) * nr_regs; }
int hw_find_range_array_property (struct hw *me, const char *property, unsigned index, range_property_spec *range) { const struct hw_property *node; unsigned sizeof_entry = (nr_range_property_cells (me, 1) * sizeof (unsigned_cell)); const unsigned_cell *cells; /* locate the property */ node = hw_find_property (me, property); if (node == NULL) hw_abort (me, "property \"%s\" not found", property); if (node->type != range_array_property) hw_abort (me, "property \"%s\" of wrong type (range array)", property); /* aligned ? */ if ((node->sizeof_array % sizeof_entry) != 0) hw_abort (me, "property \"%s\" contains an incomplete number of entries", property); /* within bounds? */ if (node->sizeof_array < sizeof_entry * (index + 1)) return 0; /* find the range of interest */ cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index); /* copy the child address out - converting as we go */ cells = cells_to_unit_address (cells, &range->child_address, hw_unit_nr_address_cells (me)); /* copy the parent address out - converting as we go */ cells = cells_to_unit_address (cells, &range->parent_address, hw_unit_nr_address_cells (hw_parent (me))); /* copy the size - converting as we go */ cells = cells_to_unit_address (cells, &range->size, hw_unit_nr_size_cells (me)); return node->sizeof_array / sizeof_entry; }
static const char * parse_size (struct hw *current, struct hw *bus, const char *chp, hw_unit *size) { int i; int nr; const char *curr = chp; memset(size, 0, sizeof(*size)); /* parse the numeric list */ size->nr_cells = hw_unit_nr_size_cells (bus); nr = 0; while (1) { char *next; size->cells[nr] = strtoul (curr, &next, 0); if (curr == next) hw_abort (current, "Problem parsing <size> %s", chp); nr += 1; if (next[0] != ',') break; if (nr == size->nr_cells) hw_abort (current, "Too many values in <size> %s", chp); curr = next + 1; } ASSERT (nr > 0 && nr <= size->nr_cells); /* right align the numbers */ for (i = 1; i <= size->nr_cells; i++) { if (i <= nr) size->cells[size->nr_cells - i] = size->cells[nr - i]; else size->cells[size->nr_cells - i] = 0; } return skip_token (chp); }