* configure.ac: Check for memmem declaration.
[deliverable/binutils-gdb.git] / sim / common / hw-ports.c
CommitLineData
c906108c 1/* Hardware ports.
9b254dd1 2 Copyright (C) 1998, 2007, 2008 Free Software Foundation, Inc.
c906108c
SS
3 Contributed by Andrew Cagney and Cygnus Solutions.
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4744ac1b
JB
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
c906108c
SS
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
4744ac1b
JB
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
19
20
21#include "hw-main.h"
22#include "hw-base.h"
23
24#ifdef HAVE_STDLIB_H
25#include <stdlib.h>
26#endif
27
28#ifdef HAVE_STRING_H
29#include <string.h>
30#else
31#ifdef HAVE_STRINGS_H
32#include <strings.h>
33#endif
34#endif
35
36#include <ctype.h>
37
38#define TRACE(x,y)
39
40
41struct hw_port_edge {
42 int my_port;
43 struct hw *dest;
44 int dest_port;
45 struct hw_port_edge *next;
46 object_disposition disposition;
47};
48
49struct hw_port_data {
50 hw_port_event_method *to_port_event;
51 const struct hw_port_descriptor *ports;
52 struct hw_port_edge *edges;
53};
54
55const struct hw_port_descriptor empty_hw_ports[] = {
56 { NULL, },
57};
58
59static void
60panic_hw_port_event (struct hw *me,
61 int my_port,
62 struct hw *source,
63 int source_port,
64 int level)
65{
66 hw_abort (me, "no port method");
67}
68
69void
70create_hw_port_data (struct hw *me)
71{
72 me->ports_of_hw = HW_ZALLOC (me, struct hw_port_data);
73 set_hw_port_event (me, panic_hw_port_event);
74 set_hw_ports (me, empty_hw_ports);
75}
76
77void
78delete_hw_port_data (struct hw *me)
79{
80 hw_free (me, me->ports_of_hw);
81 me->ports_of_hw = NULL;
82}
83
84void
85set_hw_ports (struct hw *me,
86 const struct hw_port_descriptor ports[])
87{
88 me->ports_of_hw->ports = ports;
89}
90
91void
92set_hw_port_event (struct hw *me,
93 hw_port_event_method *port_event)
94{
95 me->ports_of_hw->to_port_event = port_event;
96}
97
98
99static void
100attach_hw_port_edge (struct hw *me,
101 struct hw_port_edge **list,
102 int my_port,
103 struct hw *dest,
104 int dest_port,
105 object_disposition disposition)
106{
107 struct hw_port_edge *new_edge = HW_ZALLOC (me, struct hw_port_edge);
108 new_edge->my_port = my_port;
109 new_edge->dest = dest;
110 new_edge->dest_port = dest_port;
111 new_edge->next = *list;
112 new_edge->disposition = disposition;
113 *list = new_edge;
114}
115
116
117static void
118detach_hw_port_edge (struct hw *me,
119 struct hw_port_edge **list,
120 int my_port,
121 struct hw *dest,
122 int dest_port)
123{
124 while (*list != NULL)
125 {
126 struct hw_port_edge *old_edge = *list;
127 if (old_edge->dest == dest
128 && old_edge->dest_port == dest_port
129 && old_edge->my_port == my_port)
130 {
131 if (old_edge->disposition == permenant_object)
132 hw_abort (me, "attempt to delete permenant port edge");
133 *list = old_edge->next;
134 hw_free (me, old_edge);
135 return;
136 }
137 }
138 hw_abort (me, "attempt to delete unattached port");
139}
140
141
142#if 0
143static void
144clean_hw_port_edges (struct hw_port_edge **list)
145{
146 while (*list != NULL)
147 {
148 struct hw_port_edge *old_edge = *list;
149 switch (old_edge->disposition)
150 {
151 case permenant_object:
152 list = &old_edge->next;
153 break;
154 case temporary_object:
155 *list = old_edge->next;
156 hw_free (me, old_edge);
157 break;
158 }
159 }
160}
161#endif
162
163
164/* Ports: */
165
166void
167hw_port_event (struct hw *me,
168 int my_port,
169 int level)
170{
171 int found_an_edge = 0;
172 struct hw_port_edge *edge;
173 /* device's lines directly connected */
174 for (edge = me->ports_of_hw->edges;
175 edge != NULL;
176 edge = edge->next)
177 {
178 if (edge->my_port == my_port)
179 {
180 edge->dest->ports_of_hw->to_port_event (edge->dest,
181 edge->dest_port,
182 me,
183 my_port,
184 level);
185 found_an_edge = 1;
186 }
187 }
188 if (!found_an_edge)
189 hw_abort (me, "No edge for port %d", my_port);
190}
191
192
193void
194hw_port_attach (struct hw *me,
195 int my_port,
196 struct hw *dest,
197 int dest_port,
198 object_disposition disposition)
199{
200 attach_hw_port_edge (me,
201 &me->ports_of_hw->edges,
202 my_port,
203 dest,
204 dest_port,
205 disposition);
206}
207
208
209void
210hw_port_detach (struct hw *me,
211 int my_port,
212 struct hw *dest,
213 int dest_port)
214{
215 detach_hw_port_edge (me,
216 &me->ports_of_hw->edges,
217 my_port,
218 dest,
219 dest_port);
220}
221
222
223void
224hw_port_traverse (struct hw *me,
225 hw_port_traverse_function *handler,
226 void *data)
227{
228 struct hw_port_edge *port_edge;
229 for (port_edge = me->ports_of_hw->edges;
230 port_edge != NULL;
231 port_edge = port_edge->next)
232 {
233 handler (me, port_edge->my_port,
234 port_edge->dest, port_edge->dest_port,
235 data);
236 }
237}
238
239
240int
241hw_port_decode (struct hw *me,
242 const char *port_name,
243 port_direction direction)
244{
245 if (port_name == NULL || port_name[0] == '\0')
246 return 0;
247 if (isdigit(port_name[0]))
248 {
249 return strtoul (port_name, NULL, 0);
250 }
251 else
252 {
253 const struct hw_port_descriptor *ports =
254 me->ports_of_hw->ports;
255 if (ports != NULL)
256 {
257 while (ports->name != NULL)
258 {
259 if (ports->direction == bidirect_port
260 || ports->direction == direction)
261 {
262 if (ports->nr_ports > 0)
263 {
264 int len = strlen (ports->name);
265 if (strncmp (port_name, ports->name, len) == 0)
266 {
267 if (port_name[len] == '\0')
268 return ports->number;
269 else if(isdigit (port_name[len]))
270 {
271 int port = (ports->number
272 + strtoul (&port_name[len], NULL, 0));
273 if (port >= ports->number + ports->nr_ports)
274 hw_abort (me,
275 "Port %s out of range",
276 port_name);
277 return port;
278 }
279 }
280 }
281 else if (strcmp (port_name, ports->name) == 0)
282 return ports->number;
283 }
284 ports++;
285 }
286 }
287 }
288 hw_abort (me, "Unreconized port %s", port_name);
289 return 0;
290}
291
292
293int
294hw_port_encode (struct hw *me,
295 int port_number,
296 char *buf,
297 int sizeof_buf,
298 port_direction direction)
299{
300 const struct hw_port_descriptor *ports = NULL;
301 ports = me->ports_of_hw->ports;
302 if (ports != NULL) {
303 while (ports->name != NULL)
304 {
305 if (ports->direction == bidirect_port
306 || ports->direction == direction)
307 {
308 if (ports->nr_ports > 0)
309 {
310 if (port_number >= ports->number
311 && port_number < ports->number + ports->nr_ports)
312 {
313 strcpy (buf, ports->name);
314 sprintf (buf + strlen(buf), "%d", port_number - ports->number);
315 if (strlen (buf) >= sizeof_buf)
316 hw_abort (me, "hw_port_encode: buffer overflow");
317 return strlen (buf);
318 }
319 }
320 else
321 {
322 if (ports->number == port_number)
323 {
324 if (strlen(ports->name) >= sizeof_buf)
325 hw_abort (me, "hw_port_encode: buffer overflow");
326 strcpy(buf, ports->name);
327 return strlen(buf);
328 }
329 }
330 }
331 ports++;
332 }
333 }
334 sprintf (buf, "%d", port_number);
335 if (strlen(buf) >= sizeof_buf)
336 hw_abort (me, "hw_port_encode: buffer overflow");
337 return strlen(buf);
338}
This page took 0.37909 seconds and 4 git commands to generate.