static unsigned nr_range_property_cells (struct hw *me, int nr_ranges) { return ((hw_unit_nr_address_cells (me) + hw_unit_nr_address_cells (hw_parent (me)) + hw_unit_nr_size_cells (me)) ) * nr_ranges; }
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); }
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 int generic_hw_unit_decode (struct hw *bus, const char *unit, hw_unit *phys) { memset (phys, 0, sizeof (*phys)); if (unit == NULL) return 0; else { int nr_cells = 0; const int max_nr_cells = hw_unit_nr_address_cells (bus); while (1) { char *end = NULL; unsigned long val; val = strtoul (unit, &end, 0); /* parse error? */ if (unit == end) return -1; /* two many cells? */ if (nr_cells >= max_nr_cells) return -1; /* save it */ phys->cells[nr_cells] = val; nr_cells++; unit = end; /* more to follow? */ if (isspace (*unit) || *unit == '\0') break; if (*unit != ',') return -1; unit++; } if (nr_cells < max_nr_cells) { /* shift everything to correct position */ int i; for (i = 1; i <= nr_cells; i++) phys->cells[max_nr_cells - i] = phys->cells[nr_cells - i]; for (i = 0; i < (max_nr_cells - nr_cells); i++) phys->cells[i] = 0; } phys->nr_cells = max_nr_cells; return max_nr_cells; } }