Clean up create/delete of hw-ports

This commit is contained in:
Andrew Cagney 1998-05-25 07:08:48 +00:00
parent f675744718
commit 2f06c437e2
5 changed files with 531 additions and 54 deletions

View File

@ -1,3 +1,16 @@
Mon May 25 16:55:16 1998 Andrew Cagney <cagney@b1.cygnus.com>
* hw-base.c (panic_hw_port_event, empty_hw_ports): Move from here.
* hw-ports.c: To here.
* hw-base.h, hw-ports.c (create_hw_port_data,
delete_hw_port_data): New functions.
* hw-base.c (hw_delete, hw_create): Call same.
* hw-base.h (set_hw_ports, set_hw_port_event): Move set functions
from here.
* hw-ports.h: To here.
Mon May 25 16:42:48 1998 Andrew Cagney <cagney@b1.cygnus.com>
* hw-device.c (hw_ioctl), hw-device.h (hw_ioctl_callback): Drop

View File

@ -23,15 +23,6 @@
#include "hw-base.h"
/* LATER: #include "hwconfig.h" */
extern const struct hw_device_descriptor dv_core_descriptor[];
extern const struct hw_device_descriptor dv_pal_descriptor[];
const struct hw_device_descriptor *hw_descriptors[] = {
dv_core_descriptor,
dv_pal_descriptor,
NULL,
};
#ifdef HAVE_STRING_H
#include <string.h>
#else
@ -46,6 +37,8 @@ const struct hw_device_descriptor *hw_descriptors[] = {
#include <ctype.h>
#include "hw-config.h"
struct hw_base_data {
int finished_p;
const struct hw_device_descriptor *descriptor;
@ -222,9 +215,7 @@ panic_hw_io_read_buffer (struct hw *me,
void *dest,
int space,
unsigned_word addr,
unsigned nr_bytes,
sim_cpu *processor,
sim_cia cia)
unsigned nr_bytes)
{
hw_abort (me, "no io-read method");
return 0;
@ -235,9 +226,7 @@ panic_hw_io_write_buffer (struct hw *me,
const void *source,
int space,
unsigned_word addr,
unsigned nr_bytes,
sim_cpu *processor,
sim_cia cia)
unsigned nr_bytes)
{
hw_abort (me, "no io-write method");
return 0;
@ -272,22 +261,6 @@ passthrough_hw_dma_write_buffer (struct hw *me,
violate_read_only_section);
}
const struct hw_port_descriptor empty_hw_ports[] = {
{ NULL, },
};
static void
panic_hw_port_event (struct hw *me,
int my_port,
struct hw *source,
int source_port,
int level,
sim_cpu *processor,
sim_cia cia)
{
hw_abort (me, "no port method");
}
static void
ignore_hw_delete (struct hw *me)
{
@ -342,12 +315,12 @@ full_name_of_hw (struct hw *leaf,
/* return it usefully */
if (buf == full_name)
buf = (char *) strdup (full_name);
buf = hw_strdup (leaf, full_name);
return buf;
}
struct hw *
hw_create (SIM_DESC sd,
hw_create (struct sim_state *sd,
struct hw *parent,
const char *family,
const char *name,
@ -358,9 +331,9 @@ hw_create (SIM_DESC sd,
struct hw *hw = ZALLOC (struct hw);
/* our identity */
hw->family_of_hw = family;
hw->name_of_hw = name;
hw->args_of_hw = args;
hw->family_of_hw = hw_strdup (hw, family);
hw->name_of_hw = hw_strdup (hw, name);
hw->args_of_hw = hw_strdup (hw, args);
/* a hook into the system */
if (sd != NULL)
@ -433,6 +406,7 @@ hw_create (SIM_DESC sd,
if (strcmp (family, entry->family) == 0)
{
hw->base_of_hw->descriptor = entry;
break;
}
}
}
@ -443,8 +417,7 @@ hw_create (SIM_DESC sd,
}
/* Attach dummy ports */
set_hw_ports (hw, empty_hw_ports);
set_hw_port_event (hw, panic_hw_port_event);
create_hw_port_data (hw);
return hw;
}
@ -477,6 +450,12 @@ hw_finish (struct hw *me)
/* Fill in the (hopefully) defined trace variable */
if (hw_find_property (me, "trace?") != NULL)
me->trace_of_hw_p = hw_find_boolean_property (me, "trace?");
/* allow global variable to define default tracing */
else if (! hw_trace_p (me)
&& hw_find_property (hw_root (me), "global-trace?") != NULL
&& hw_find_boolean_property (hw_root (me), "global-trace?"))
me->trace_of_hw_p = 1;
/* Allow the real device to override any methods */
me->base_of_hw->descriptor->to_finish (me);
@ -490,6 +469,8 @@ hw_delete (struct hw *me)
/* give the object a chance to tidy up */
me->base_of_hw->to_delete (me);
delete_hw_port_data (me);
/* now unlink us from the tree */
if (hw_parent (me))
{

View File

@ -42,7 +42,7 @@ struct hw_device_descriptor {
/* Create a primative device */
struct hw *hw_create
(SIM_DESC sd,
(struct sim_state *sd,
struct hw *parent,
const char *family,
const char *name,
@ -106,23 +106,38 @@ typedef void (hw_delete_callback)
((hw)->base_of_hw->to_delete = (method))
struct hw_port_descriptor {
const char *name;
int number;
int nr_ports;
port_direction direction;
/* Helper functions to make the implementation of a device easier */
/* Go through the devices reg properties and look for those specifying
an address to attach various registers to */
void do_hw_attach_regs (struct hw *me);
/* Perform a polling read on FD returning either the number of bytes
or a hw_io status code that indicates the reason for the read
failure */
enum {
HW_IO_EOF = -1, HW_IO_NOT_READY = -2, /* See: IEEE 1275 */
};
typedef void (hw_port_event_callback)
(struct hw *me,
int my_port,
struct hw *source,
int source_port,
int level,
sim_cpu *processor,
sim_cia cia);
typedef int (do_hw_poll_read_method)
(SIM_DESC sd, int, char *, int);
int do_hw_poll_read
(struct hw *me,
do_hw_poll_read_method *read,
int sim_io_fd,
void *buf,
unsigned size_of_buf);
/* PORTS */
extern void create_hw_port_data
(struct hw *hw);
extern void delete_hw_port_data
(struct hw *hw);
extern void set_hw_ports (struct hw *hw, const struct hw_port_descriptor ports[]);
extern void set_hw_port_event (struct hw *hw, hw_port_event_callback *to_port_event);
#endif

339
sim/common/hw-ports.c Normal file
View File

@ -0,0 +1,339 @@
/* Common hardware.
Copyright (C) 1998 Free Software Foundation, Inc.
Contributed by Andrew Cagney and Cygnus Solutions.
This file is part of GDB, the GNU debugger.
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, 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 "sim-main.h"
#include "hw-base.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include <ctype.h>
#define TRACE(x,y)
struct hw_port_edge {
int my_port;
struct hw *dest;
int dest_port;
struct hw_port_edge *next;
object_disposition disposition;
};
struct hw_port_data {
hw_port_event_callback *to_port_event;
const struct hw_port_descriptor *ports;
struct hw_port_edge *edges;
};
const struct hw_port_descriptor empty_hw_ports[] = {
{ NULL, },
};
static void
panic_hw_port_event (struct hw *me,
int my_port,
struct hw *source,
int source_port,
int level)
{
hw_abort (me, "no port method");
}
void
create_hw_port_data (struct hw *me)
{
me->ports_of_hw = HW_ZALLOC (me, struct hw_port_data);
set_hw_port_event (me, panic_hw_port_event);
set_hw_ports (me, empty_hw_ports);
}
void
delete_hw_port_data (struct hw *me)
{
hw_free (me, me->ports_of_hw);
me->ports_of_hw = NULL;
}
void
set_hw_ports (struct hw *me,
const struct hw_port_descriptor ports[])
{
me->ports_of_hw->ports = ports;
}
void
set_hw_port_event (struct hw *me,
hw_port_event_callback *port_event)
{
me->ports_of_hw->to_port_event = port_event;
}
static void
attach_hw_port_edge (struct hw *me,
struct hw_port_edge **list,
int my_port,
struct hw *dest,
int dest_port,
object_disposition disposition)
{
struct hw_port_edge *new_edge = HW_ZALLOC (me, struct hw_port_edge);
new_edge->my_port = my_port;
new_edge->dest = dest;
new_edge->dest_port = dest_port;
new_edge->next = *list;
new_edge->disposition = disposition;
*list = new_edge;
}
static void
detach_hw_port_edge (struct hw *me,
struct hw_port_edge **list,
int my_port,
struct hw *dest,
int dest_port)
{
while (*list != NULL)
{
struct hw_port_edge *old_edge = *list;
if (old_edge->dest == dest
&& old_edge->dest_port == dest_port
&& old_edge->my_port == my_port)
{
if (old_edge->disposition == permenant_object)
hw_abort (me, "attempt to delete permenant port edge");
*list = old_edge->next;
hw_free (me, old_edge);
return;
}
}
hw_abort (me, "attempt to delete unattached port");
}
#if 0
static void
clean_hw_port_edges (struct hw_port_edge **list)
{
while (*list != NULL)
{
struct hw_port_edge *old_edge = *list;
switch (old_edge->disposition)
{
case permenant_object:
list = &old_edge->next;
break;
case temporary_object:
*list = old_edge->next;
hw_free (me, old_edge);
break;
}
}
}
#endif
/* Ports: */
void
hw_port_event (struct hw *me,
int my_port,
int level)
{
int found_an_edge = 0;
struct hw_port_edge *edge;
/* device's lines directly connected */
for (edge = me->ports_of_hw->edges;
edge != NULL;
edge = edge->next)
{
if (edge->my_port == my_port)
{
edge->dest->ports_of_hw->to_port_event (edge->dest,
edge->dest_port,
me,
my_port,
level);
found_an_edge = 1;
}
}
if (!found_an_edge)
hw_abort (me, "No edge for port %d", my_port);
}
void
hw_port_attach (struct hw *me,
int my_port,
struct hw *dest,
int dest_port,
object_disposition disposition)
{
attach_hw_port_edge (me,
&me->ports_of_hw->edges,
my_port,
dest,
dest_port,
disposition);
}
void
hw_port_detach (struct hw *me,
int my_port,
struct hw *dest,
int dest_port)
{
detach_hw_port_edge (me,
&me->ports_of_hw->edges,
my_port,
dest,
dest_port);
}
void
hw_port_traverse (struct hw *me,
hw_port_traverse_function *handler,
void *data)
{
struct hw_port_edge *port_edge;
for (port_edge = me->ports_of_hw->edges;
port_edge != NULL;
port_edge = port_edge->next)
{
handler (me, port_edge->my_port,
port_edge->dest, port_edge->dest_port,
data);
}
}
int
hw_port_decode (struct hw *me,
const char *port_name,
port_direction direction)
{
if (port_name == NULL || port_name[0] == '\0')
return 0;
if (isdigit(port_name[0]))
{
return strtoul (port_name, NULL, 0);
}
else
{
const struct hw_port_descriptor *ports =
me->ports_of_hw->ports;
if (ports != NULL)
{
while (ports->name != NULL)
{
if (ports->direction == bidirect_port
|| ports->direction == direction)
{
if (ports->nr_ports > 0)
{
int len = strlen (ports->name);
if (strncmp (port_name, ports->name, len) == 0)
{
if (port_name[len] == '\0')
return ports->number;
else if(isdigit (port_name[len]))
{
int port = (ports->number
+ strtoul (&port_name[len], NULL, 0));
if (port >= ports->number + ports->nr_ports)
hw_abort (me,
"Port %s out of range",
port_name);
return port;
}
}
}
else if (strcmp (port_name, ports->name) == 0)
return ports->number;
}
ports++;
}
}
}
hw_abort (me, "Unreconized port %s", port_name);
return 0;
}
int
hw_port_encode (struct hw *me,
int port_number,
char *buf,
int sizeof_buf,
port_direction direction)
{
const struct hw_port_descriptor *ports = NULL;
ports = me->ports_of_hw->ports;
if (ports != NULL) {
while (ports->name != NULL)
{
if (ports->direction == bidirect_port
|| ports->direction == direction)
{
if (ports->nr_ports > 0)
{
if (port_number >= ports->number
&& port_number < ports->number + ports->nr_ports)
{
strcpy (buf, ports->name);
sprintf (buf + strlen(buf), "%d", port_number - ports->number);
if (strlen (buf) >= sizeof_buf)
hw_abort (me, "hw_port_encode: buffer overflow");
return strlen (buf);
}
}
else
{
if (ports->number == port_number)
{
if (strlen(ports->name) >= sizeof_buf)
hw_abort (me, "hw_port_encode: buffer overflow");
strcpy(buf, ports->name);
return strlen(buf);
}
}
}
ports++;
}
}
sprintf (buf, "%d", port_number);
if (strlen(buf) >= sizeof_buf)
hw_abort (me, "hw_port_encode: buffer overflow");
return strlen(buf);
}

129
sim/common/hw-ports.h Normal file
View File

@ -0,0 +1,129 @@
/* Common hardware.
Copyright (C) 1998 Free Software Foundation, Inc.
Contributed by Andrew Cagney and Cygnus Solutions.
This file is part of GDB, the GNU debugger.
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, 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_PORTS_H
#define HW_PORTS_H
/* Initialize a port */
struct hw_port_descriptor {
const char *name;
int number;
int nr_ports;
port_direction direction;
};
void set_hw_ports (struct hw *hw, const struct hw_port_descriptor ports[]);
typedef void (hw_port_event_callback)
(struct hw *me,
int my_port,
struct hw *source,
int source_port,
int level);
void set_hw_port_event (struct hw *hw, hw_port_event_callback *to_port_event);
/* Port source
A device drives its output ports using the call
*/
void hw_port_event
(struct hw *me,
int my_port,
int value);
/* This port event will then be propogated to any attached
destination ports.
Any interpretation of PORT and VALUE is model dependant. As a
guideline the following are recommended: PCI interrupts A-D should
correspond to ports 0-3; level sensative interrupts be requested
with a value of one and withdrawn with a value of 0; edge sensative
interrupts always have a value of 1, the event its self is treated
as the interrupt.
Port destinations
Attached to each port of a device can be zero or more
desitinations. These destinations consist of a device/port pair.
A destination is attached/detached to a device line using the
attach and detach calls. */
void hw_port_attach
(struct hw *me,
int my_port,
struct hw *dest,
int dest_port,
object_disposition disposition);
void hw_port_detach
(struct hw *me,
int my_port,
struct hw *dest,
int dest_port);
/* Iterate over the list of ports attached to a device */
typedef void (hw_port_traverse_function)
(struct hw *me,
int my_port,
struct hw *dest,
int dest_port,
void *data);
void hw_port_traverse
(struct hw *me,
hw_port_traverse_function *handler,
void *data);
/* DESTINATION is attached (detached) to LINE of the device ME
Port conversion
Users refer to port numbers symbolically. For instance a device
may refer to its `INT' signal which is internally represented by
port 3.
To convert to/from the symbolic and internal representation of a
port name/number. The following functions are available. */
int hw_port_decode
(struct hw *me,
const char *symbolic_name,
port_direction direction);
int hw_port_encode
(struct hw *me,
int port_number,
char *buf,
int sizeof_buf,
port_direction direction);
#endif