diff --git a/sim/common/.Sanitize b/sim/common/.Sanitize index 240f3d3bd7..2948748dc2 100644 --- a/sim/common/.Sanitize +++ b/sim/common/.Sanitize @@ -65,6 +65,10 @@ hw-device.c hw-device.h hw-events.c hw-events.h +hw-handles.c +hw-handles.h +hw-instances.c +hw-instances.h hw-main.h hw-ports.c hw-ports.h diff --git a/sim/common/hw-handles.c b/sim/common/hw-handles.c new file mode 100644 index 0000000000..a62c015514 --- /dev/null +++ b/sim/common/hw-handles.c @@ -0,0 +1,237 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995,1997-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "hw-main.h" +#include "hw-base.h" + + +struct hw_handle_mapping { + cell_word external; + struct hw *phandle; + struct hw_instance *ihandle; + struct hw_handle_mapping *next; +}; + + +struct hw_handle_data { + int nr_mappings; + struct hw_handle_mapping *mappings; +}; + +void +create_hw_handle_data (struct hw *hw) +{ + if (hw_parent (hw) == NULL) + { + hw->handles_of_hw = HW_ZALLOC (hw, struct hw_handle_data); + } + else + { + hw->handles_of_hw = hw_root (hw)->handles_of_hw; + } +} + +void +delete_hw_handle_data (struct hw *hw) +{ + /* NULL */ +} + + + +#if 0 +void +hw_handle_init (struct hw *hw) +{ + struct hw_handle_mapping *current_map = db->mappings; + if (current_map != NULL) + { + db->nr_mappings = db->mappings->external; + /* verify that the mappings that were not removed are in + sequence down to nr 1 */ + while (current_map->next != NULL) + { + if (current_map->external != current_map->next->external + 1) + error ("hw_handle: hw_handle database possibly corrupt"); + current_map = current_map->next; + } + ASSERT (current_map->next == NULL); + if (current_map->external != 1) + error ("hw_handle: hw_handle database possibly corrupt"); + } + else + { + db->nr_mappings = 0; + } +} +#endif + + +struct hw_instance * +hw_handle_ihandle2 (struct hw *hw, + cell_word external) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping *current_map = db->mappings; + while (current_map != NULL) + { + if (current_map->external == external) + return current_map->ihandle; + current_map = current_map->next; + } + return (void*)0; +} + + +struct hw * +hw_handle_phandle2 (struct hw *hw, + cell_word external) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping *current_map = db->mappings; + while (current_map != NULL) + { + if (current_map->external == external) + return current_map->phandle; + current_map = current_map->next; + } + return (void*)0; +} + + +cell_word +hw_handle_2ihandle (struct hw *hw, + struct hw_instance *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping *current_map = db->mappings; + while (current_map != NULL) + { + if (current_map->ihandle == internal) + return current_map->external; + current_map = current_map->next; + } + return 0; +} + + +cell_word +hw_handle_2phandle (struct hw *hw, + struct hw *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping *current_map = db->mappings; + while (current_map != NULL) + { + if (current_map->phandle == internal) + return current_map->external; + current_map = current_map->next; + } + return 0; +} + + +void +hw_handle_add_ihandle (struct hw *hw, + struct hw_instance *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + if (hw_handle_2ihandle (hw, internal) != NULL) + { + hw_abort (hw, "attempting to add an ihandle already in the data base"); + } + else + { + /* insert at the front making things in decending order */ + struct hw_handle_mapping *new_map = ZALLOC (struct hw_handle_mapping); + new_map->next = db->mappings; + new_map->ihandle = internal; + db->nr_mappings += 1; + new_map->external = db->nr_mappings; + db->mappings = new_map; + } +} + + +void +hw_handle_add_phandle (struct hw *hw, + struct hw *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + if (hw_handle_2phandle (hw, internal) != NULL) + { + hw_abort (hw, "attempting to add a phandle already in the data base"); + } + else + { + /* insert at the front making things in decending order */ + struct hw_handle_mapping *new_map = ZALLOC (struct hw_handle_mapping); + new_map->next = db->mappings; + new_map->phandle = internal; + db->nr_mappings += 1; + new_map->external = db->nr_mappings; + db->mappings = new_map; + } +} + + +void +hw_handle_remove_ihandle (struct hw *hw, + struct hw_instance *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping **current_map = &db->mappings; + while (*current_map != NULL) + { + if ((*current_map)->ihandle == internal) + { + struct hw_handle_mapping *delete = *current_map; + *current_map = delete->next; + zfree (delete); + return; + } + current_map = &(*current_map)->next; + } + hw_abort (hw, "attempt to remove nonexistant ihandle"); +} + + +void +hw_handle_remove_phandle (struct hw *hw, + struct hw *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping **current_map = &db->mappings; + while (*current_map != NULL) + { + if ((*current_map)->phandle == internal) + { + struct hw_handle_mapping *delete = *current_map; + *current_map = delete->next; + zfree (delete); + return; + } + current_map = &(*current_map)->next; + } + hw_abort (hw, "attempt to remove nonexistant phandle"); +} + + diff --git a/sim/common/hw-handles.h b/sim/common/hw-handles.h new file mode 100644 index 0000000000..087c9d02e7 --- /dev/null +++ b/sim/common/hw-handles.h @@ -0,0 +1,63 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995,1997-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef HW_HANDLES_H +#define HW_HANDLES_H + + +/* Export a capability (handle) data base that maps between internal + data values and those given to a simulation. */ + + +cell_word hw_handle_2ihandle +(struct hw *db, + struct hw_instance *instance); + +struct hw_instance *hw_handle_ihandle2 +(struct hw *db, + cell_word external); + +void hw_handle_add_ihandle +(struct hw *db, + struct hw_instance *instance); + +void hw_handle_remove_ihandle +(struct hw *db, + struct hw_instance *instance); + + +cell_word hw_handle_2phandle +(struct hw *db, + struct hw *hw); + +struct hw *hw_handle_phandle2 +(struct hw *db, + cell_word external); + +void hw_handle_add_phandle +(struct hw *db, + struct hw *hw); + +void hw_handle_remove_phandle +(struct hw *db, + struct hw *hw); + +#endif diff --git a/sim/common/hw-instances.c b/sim/common/hw-instances.c new file mode 100644 index 0000000000..31393b141d --- /dev/null +++ b/sim/common/hw-instances.c @@ -0,0 +1,285 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "hw-main.h" +#include "hw-base.h" + +#define ASSERT(X) + +struct hw_instance_data { + hw_finish_instance_method *to_finish; + struct hw_instance *instances; +}; + +static hw_finish_instance_method abort_hw_finish_instance; + +void +create_hw_instance_data (struct hw *me) +{ + me->instances_of_hw = HW_ZALLOC (me, struct hw_instance_data); + set_hw_finish_instance (me, abort_hw_finish_instance); +} + +void +delete_hw_instance_data (struct hw *me) +{ + /* NOP */ +} + + +static void +abort_hw_finish_instance (struct hw *hw, + struct hw_instance *instance) +{ + hw_abort (hw, "no instance finish method"); +} + +void +set_hw_finish_instance (struct hw *me, + hw_finish_instance_method *finish) +{ + me->instances_of_hw->to_finish = finish; +} + + +#if 0 +void +clean_hw_instances (struct hw *me) +{ + struct hw_instance **instance = &me->instances; + while (*instance != NULL) + { + struct hw_instance *old_instance = *instance; + hw_instance_delete (old_instance); + instance = &me->instances; + } +} +#endif + + +void +hw_instance_delete (struct hw_instance *instance) +{ +#if 1 + hw_abort (hw_instance_hw (instance), "not implemented"); +#else + struct hw *me = hw_instance_hw (instance); + if (instance->to_instance_delete == NULL) + hw_abort (me, "no delete method"); + instance->method->delete(instance); + if (instance->args != NULL) + zfree (instance->args); + if (instance->path != NULL) + zfree (instance->path); + if (instance->child == NULL) + { + /* only remove leaf nodes */ + struct hw_instance **curr = &me->instances; + while (*curr != instance) + { + ASSERT (*curr != NULL); + curr = &(*curr)->next; + } + *curr = instance->next; + } + else + { + /* check it isn't in the instance list */ + struct hw_instance *curr = me->instances; + while (curr != NULL) + { + ASSERT(curr != instance); + curr = curr->next; + } + /* unlink the child */ + ASSERT (instance->child->parent == instance); + instance->child->parent = NULL; + } + cap_remove (me->ihandles, instance); + zfree (instance); +#endif +} + + +static int +panic_hw_instance_read (struct hw_instance *instance, + void *addr, + unsigned_word len) +{ + hw_abort (hw_instance_hw (instance), "no read method"); + return -1; +} + + + +static int +panic_hw_instance_write (struct hw_instance *instance, + const void *addr, + unsigned_word len) +{ + hw_abort (hw_instance_hw (instance), "no write method"); + return -1; +} + + +static int +panic_hw_instance_seek (struct hw_instance *instance, + unsigned_word pos_hi, + unsigned_word pos_lo) +{ + hw_abort (hw_instance_hw (instance), "no seek method"); + return -1; +} + + +int +hw_instance_call_method (struct hw_instance *instance, + const char *method_name, + int n_stack_args, + unsigned_cell stack_args[/*n_stack_args*/], + int n_stack_returns, + unsigned_cell stack_returns[/*n_stack_args*/]) +{ +#if 1 + hw_abort (hw_instance_hw (instance), "not implemented"); + return -1; +#else + struct hw *me = instance->owner; + const hw_instance_methods *method = instance->method->methods; + if (method == NULL) + { + hw_abort (me, "no methods (want %s)", method_name); + } + while (method->name != NULL) + { + if (strcmp(method->name, method_name) == 0) + { + return method->method (instance, + n_stack_args, stack_args, + n_stack_returns, stack_returns); + } + method++; + } + hw_abort (me, "no %s method", method_name); + return 0; +#endif +} + + +#define set_hw_instance_read(instance, method)\ +((instance)->to_instance_read = (method)) + +#define set_hw_instance_write(instance, method)\ +((instance)->to_instance_write = (method)) + +#define set_hw_instance_seek(instance, method)\ +((instance)->to_instance_seek = (method)) + + +#if 0 +static void +set_hw_instance_finish (struct hw *me, + hw_instance_finish_method *method) +{ + if (me->instances_of_hw == NULL) + me->instances_of_hw = HW_ZALLOC (me, struct hw_instance_data); + me->instances_of_hw->to_finish = method; +} +#endif + + +struct hw_instance * +hw_instance_create (struct hw *me, + struct hw_instance *parent, + const char *path, + const char *args) +{ + struct hw_instance *instance = ZALLOC (struct hw_instance); + /*instance->unit*/ + /* link this instance into the devices list */ + instance->hw_of_instance = me; + instance->parent_of_instance = NULL; + /* link this instance into the front of the devices instance list */ + instance->sibling_of_instance = me->instances_of_hw->instances; + me->instances_of_hw->instances = instance; + if (parent != NULL) + { + ASSERT (parent->child_of_instance == NULL); + parent->child_of_instance = instance; + instance->parent_of_instance = parent; + } + instance->args_of_instance = hw_strdup (me, args); + instance->path_of_instance = hw_strdup (me, path); + set_hw_instance_read (instance, panic_hw_instance_read); + set_hw_instance_write (instance, panic_hw_instance_write); + set_hw_instance_seek (instance, panic_hw_instance_seek); + hw_handle_add_ihandle (me, instance); + me->instances_of_hw->to_finish (me, instance); + return instance; +} + + +struct hw_instance * +hw_instance_interceed (struct hw_instance *parent, + const char *path, + const char *args) +{ +#if 1 + return NULL; +#else + struct hw_instance *instance = ZALLOC (struct hw_instance); + /*instance->unit*/ + /* link this instance into the devices list */ + if (me != NULL) + { + ASSERT (parent == NULL); + instance->hw_of_instance = me; + instance->parent_of_instance = NULL; + /* link this instance into the front of the devices instance list */ + instance->sibling_of_instance = me->instances_of_hw->instances; + me->instances_of_hw->instances = instance; + } + if (parent != NULL) + { + struct hw_instance **previous; + ASSERT (parent->child_of_instance == NULL); + parent->child_of_instance = instance; + instance->owner = parent->owner; + instance->parent_of_instance = parent; + /* in the devices instance list replace the parent instance with + this one */ + instance->next = parent->next; + /* replace parent with this new node */ + previous = &instance->owner->instances; + while (*previous != parent) + { + ASSERT (*previous != NULL); + previous = &(*previous)->next; + } + *previous = instance; + } + instance->data = data; + instance->args = (args == NULL ? NULL : (char *) strdup(args)); + instance->path = (path == NULL ? NULL : (char *) strdup(path)); + cap_add (instance->owner->ihandles, instance); + return instance; +#endif +} diff --git a/sim/common/hw-instances.h b/sim/common/hw-instances.h new file mode 100644 index 0000000000..6d27b11487 --- /dev/null +++ b/sim/common/hw-instances.h @@ -0,0 +1,157 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef HW_INSTANCES_H +#define HW_INSTANCES_H + +/* Instances: + + As with IEEE1275, a device can be opened, creating an instance. + Instances provide more abstract interfaces to the underlying + hardware. For example, the instance methods for a disk may include + code that is able to interpret file systems found on disks. Such + methods would there for allow the manipulation of files on the + disks file system. The operations would be implemented using the + basic block I/O model provided by the disk. + + This model includes methods that faciliate the creation of device + instance and (should a given device support it) standard operations + on those instances. + + */ + + +struct hw_instance; + + +typedef void (hw_finish_instance_method) + (struct hw *hw, + struct hw_instance *); + +extern void set_hw_finish_instance +(struct hw *hw, + hw_finish_instance_method *method); + + +/* construct an instance of the hardware */ + +struct hw_instance *hw_instance_create +(struct hw *hw, + struct hw_instance *parent, + const char *path, + const char *args); + +struct hw_instance *hw_instance_interceed +(struct hw_instance *parent, + const char *path, + const char *args); + +void hw_instance_delete +(struct hw_instance *instance); + + +/* methods applied to an instance of the hw */ + +typedef int (hw_instance_read_method) + (struct hw_instance *instance, + void *addr, + unsigned_cell len); + +#define hw_instance_read(instance, addr, len) \ +((instance)->to_instance_read ((instance), (addr), (len))) + +#define set_hw_instance_read(instance, method) \ +((instance)->to_instance_read = (method)) + + +typedef int (hw_instance_write_method) + (struct hw_instance *instance, + const void *addr, + unsigned_cell len); + +#define hw_instance_write(instance, addr, len) \ +((instance)->to_instance_write ((instance), (addr), (len))) + +#define set_hw_instance_write(instance, method) \ +((instance)->to_instance_write = (method)) + + +typedef int (hw_instance_seek_method) + (struct hw_instance *instance, + unsigned_cell pos_hi, + unsigned_cell pos_lo); + +#define hw_instance_seek(instance, pos_hi, pos_lo) \ +((instance)->to_instance_seek ((instance), (pos_hi), (pos_lo))); + +#define set_hw_instance_seek(instance, method) \ +((instance)->to_instance_seek = (method)) + + +int hw_instance_call_method +(struct hw_instance *instance, + const char *method, + int n_stack_args, + unsigned_cell stack_args[/*n_stack_args + 1(NULL)*/], + int n_stack_returns, + unsigned_cell stack_returns[/*n_stack_returns + 1(NULL)*/]); + + + +/* the definition of the instance */ + +#define hw_instance_hw(instance) ((instance)->hw_of_instance + 0) + +#define hw_instance_path(instance) ((instance)->path_of_instance + 0) + +#define hw_instance_args(instance) ((instance)->args_of_instance) + +#define hw_instance_data(instance) ((instance)->data_of_instance) + +#define hw_instance_system(instance) (hw_system (hw_instance_hw (instance))) + + + +/* Finally an instance of a hardware device - keep your grubby little + mits off of these internals! :-) */ + +struct hw_instance { + + void *data_of_instance; + char *args_of_instance; + char *path_of_instance; + + /* the device that owns the instance */ + struct hw *hw_of_instance; + struct hw_instance *sibling_of_instance; + + /* interposed instance */ + struct hw_instance *parent_of_instance; + struct hw_instance *child_of_instance; + + /* methods */ + hw_instance_read_method *to_instance_read; + hw_instance_write_method *to_instance_write; + hw_instance_seek_method *to_instance_seek; + +}; + +#endif