#ifndef _DEVICE_TABLE_C_
#define _DEVICE_TABLE_C_
#include "device_table.h"
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <ctype.h>
void
generic_device_init_address(device *me)
{
static const char *(reg_property_names[]) = {
"attach-addresses",
"assigned-addresses",
"reg",
"alternate-reg" ,
NULL
};
const char **reg_property_name;
int nr_valid_reg_properties = 0;
for (reg_property_name = reg_property_names;
*reg_property_name != NULL;
reg_property_name++) {
if (device_find_property(me, *reg_property_name) != NULL) {
reg_property_spec reg;
int reg_entry;
for (reg_entry = 0;
device_find_reg_array_property(me, *reg_property_name, reg_entry,
®);
reg_entry++) {
unsigned_word attach_address;
int attach_space;
unsigned attach_size;
if (!device_address_to_attach_address(device_parent(me),
®.address,
&attach_space, &attach_address,
me))
continue;
if (!device_size_to_attach_size(device_parent(me),
®.size,
&attach_size, me))
continue;
device_attach_address(device_parent(me),
attach_callback,
attach_space, attach_address, attach_size,
access_read_write_exec,
me);
nr_valid_reg_properties++;
}
if (reg_property_name == reg_property_names)
break;
}
}
}
int
generic_device_unit_decode(device *bus,
const char *unit,
device_unit *phys)
{
memset(phys, 0, sizeof(device_unit));
if (unit == NULL)
return 0;
else {
int nr_cells = 0;
const int max_nr_cells = device_nr_address_cells(bus);
while (1) {
char *end = NULL;
unsigned long val;
val = strtoul(unit, &end, 0);
if (unit == end)
return -1;
if (nr_cells >= max_nr_cells)
return -1;
phys->cells[nr_cells] = val;
nr_cells++;
unit = end;
if (isspace(*unit) || *unit == '\0')
break;
if (*unit != ',')
return -1;
unit++;
}
if (nr_cells < max_nr_cells) {
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;
}
}
int
generic_device_unit_encode(device *bus,
const device_unit *phys,
char *buf,
int sizeof_buf)
{
int i;
int len;
char *pos = buf;
for (i = 0; i < phys->nr_cells; i++) {
if (phys->cells[i] != 0)
break;
}
if (phys->nr_cells == 0) {
strcpy(pos, "");
len = 0;
}
else if (i == phys->nr_cells) {
strcpy(pos, "0");
len = 1;
}
else {
for (; i < phys->nr_cells; i++) {
if (pos != buf) {
strcat(pos, ",");
pos = strchr(pos, '\0');
}
if (phys->cells[i] < 10)
sprintf(pos, "%ld", (unsigned long)phys->cells[i]);
else
sprintf(pos, "0x%lx", (unsigned long)phys->cells[i]);
pos = strchr(pos, '\0');
}
len = pos - buf;
}
if (len >= sizeof_buf)
error("generic_unit_encode - buffer overflow\n");
return len;
}
int
generic_device_address_to_attach_address(device *me,
const device_unit *address,
int *attach_space,
unsigned_word *attach_address,
device *client)
{
int i;
for (i = 0; i < address->nr_cells - 2; i++) {
if (address->cells[i] != 0)
device_error(me, "Only 32bit addresses supported");
}
if (address->nr_cells >= 2)
*attach_space = address->cells[address->nr_cells - 2];
else
*attach_space = 0;
*attach_address = address->cells[address->nr_cells - 1];
return 1;
}
int
generic_device_size_to_attach_size(device *me,
const device_unit *size,
unsigned *nr_bytes,
device *client)
{
int i;
for (i = 0; i < size->nr_cells - 1; i++) {
if (size->cells[i] != 0)
device_error(me, "Only 32bit sizes supported");
}
*nr_bytes = size->cells[0];
return *nr_bytes;
}
void
passthrough_device_address_attach(device *me,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
device *client)
{
device_attach_address(device_parent(me), attach,
space, addr, nr_bytes,
access,
client);
}
void
passthrough_device_address_detach(device *me,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
device *client)
{
device_detach_address(device_parent(me), attach,
space, addr, nr_bytes, access,
client);
}
unsigned
passthrough_device_dma_read_buffer(device *me,
void *dest,
int space,
unsigned_word addr,
unsigned nr_bytes)
{
return device_dma_read_buffer(device_parent(me), dest,
space, addr, nr_bytes);
}
unsigned
passthrough_device_dma_write_buffer(device *me,
const void *source,
int space,
unsigned_word addr,
unsigned nr_bytes,
int violate_read_only_section)
{
return device_dma_write_buffer(device_parent(me), source,
space, addr,
nr_bytes,
violate_read_only_section);
}
int
ignore_device_unit_decode(device *me,
const char *unit,
device_unit *phys)
{
memset(phys, 0, sizeof(device_unit));
return 0;
}
static const device_callbacks passthrough_callbacks = {
{ NULL, },
{ passthrough_device_address_attach,
passthrough_device_address_detach, },
{ NULL, },
{ passthrough_device_dma_read_buffer, passthrough_device_dma_write_buffer, },
{ NULL, },
{ generic_device_unit_decode,
generic_device_unit_encode, },
};
static const device_descriptor ob_device_table[] = {
{ "aliases", NULL, &passthrough_callbacks },
{ "options", NULL, &passthrough_callbacks },
{ "chosen", NULL, &passthrough_callbacks },
{ "packages", NULL, &passthrough_callbacks },
{ "cpus", NULL, &passthrough_callbacks },
{ "openprom", NULL, &passthrough_callbacks },
{ "init", NULL, &passthrough_callbacks },
{ NULL },
};
const device_descriptor *const device_table[] = {
ob_device_table,
#include "hw.c"
NULL,
};
#endif