]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/hw-ports.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / common / hw-ports.c
CommitLineData
c906108c 1/* Hardware ports.
8acc9f48 2 Copyright (C) 1998-2013 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
c906108c 38
12c4cbd5
MF
39struct hw_port_edge
40{
c906108c
SS
41 int my_port;
42 struct hw *dest;
43 int dest_port;
44 struct hw_port_edge *next;
45 object_disposition disposition;
46};
47
12c4cbd5
MF
48struct hw_port_data
49{
c906108c
SS
50 hw_port_event_method *to_port_event;
51 const struct hw_port_descriptor *ports;
52 struct hw_port_edge *edges;
53};
54
12c4cbd5
MF
55const struct hw_port_descriptor empty_hw_ports[] =
56{
21cf617c 57 { NULL, 0, 0, 0 },
c906108c
SS
58};
59
60static void
61panic_hw_port_event (struct hw *me,
62 int my_port,
63 struct hw *source,
64 int source_port,
65 int level)
66{
67 hw_abort (me, "no port method");
68}
69
70void
71create_hw_port_data (struct hw *me)
72{
73 me->ports_of_hw = HW_ZALLOC (me, struct hw_port_data);
74 set_hw_port_event (me, panic_hw_port_event);
75 set_hw_ports (me, empty_hw_ports);
76}
77
78void
79delete_hw_port_data (struct hw *me)
80{
81 hw_free (me, me->ports_of_hw);
82 me->ports_of_hw = NULL;
83}
84
85void
86set_hw_ports (struct hw *me,
87 const struct hw_port_descriptor ports[])
88{
89 me->ports_of_hw->ports = ports;
90}
91
92void
93set_hw_port_event (struct hw *me,
94 hw_port_event_method *port_event)
95{
96 me->ports_of_hw->to_port_event = port_event;
97}
98
99
100static void
101attach_hw_port_edge (struct hw *me,
102 struct hw_port_edge **list,
103 int my_port,
104 struct hw *dest,
105 int dest_port,
106 object_disposition disposition)
107{
108 struct hw_port_edge *new_edge = HW_ZALLOC (me, struct hw_port_edge);
109 new_edge->my_port = my_port;
110 new_edge->dest = dest;
111 new_edge->dest_port = dest_port;
112 new_edge->next = *list;
113 new_edge->disposition = disposition;
114 *list = new_edge;
115}
116
117
118static void
119detach_hw_port_edge (struct hw *me,
120 struct hw_port_edge **list,
121 int my_port,
122 struct hw *dest,
123 int dest_port)
124{
125 while (*list != NULL)
126 {
127 struct hw_port_edge *old_edge = *list;
128 if (old_edge->dest == dest
129 && old_edge->dest_port == dest_port
130 && old_edge->my_port == my_port)
131 {
132 if (old_edge->disposition == permenant_object)
133 hw_abort (me, "attempt to delete permenant port edge");
134 *list = old_edge->next;
135 hw_free (me, old_edge);
136 return;
137 }
138 }
139 hw_abort (me, "attempt to delete unattached port");
140}
141
142
143#if 0
144static void
145clean_hw_port_edges (struct hw_port_edge **list)
146{
147 while (*list != NULL)
148 {
149 struct hw_port_edge *old_edge = *list;
150 switch (old_edge->disposition)
151 {
152 case permenant_object:
153 list = &old_edge->next;
154 break;
155 case temporary_object:
156 *list = old_edge->next;
157 hw_free (me, old_edge);
158 break;
159 }
160 }
161}
162#endif
163
164
165/* Ports: */
166
167void
168hw_port_event (struct hw *me,
169 int my_port,
170 int level)
171{
172 int found_an_edge = 0;
173 struct hw_port_edge *edge;
174 /* device's lines directly connected */
175 for (edge = me->ports_of_hw->edges;
176 edge != NULL;
177 edge = edge->next)
178 {
179 if (edge->my_port == my_port)
180 {
181 edge->dest->ports_of_hw->to_port_event (edge->dest,
182 edge->dest_port,
183 me,
184 my_port,
185 level);
186 found_an_edge = 1;
187 }
188 }
189 if (!found_an_edge)
190 hw_abort (me, "No edge for port %d", my_port);
191}
192
193
194void
195hw_port_attach (struct hw *me,
196 int my_port,
197 struct hw *dest,
198 int dest_port,
199 object_disposition disposition)
200{
201 attach_hw_port_edge (me,
202 &me->ports_of_hw->edges,
203 my_port,
204 dest,
205 dest_port,
206 disposition);
207}
208
209
210void
211hw_port_detach (struct hw *me,
212 int my_port,
213 struct hw *dest,
214 int dest_port)
215{
216 detach_hw_port_edge (me,
217 &me->ports_of_hw->edges,
218 my_port,
219 dest,
220 dest_port);
221}
222
223
224void
225hw_port_traverse (struct hw *me,
226 hw_port_traverse_function *handler,
227 void *data)
228{
229 struct hw_port_edge *port_edge;
230 for (port_edge = me->ports_of_hw->edges;
231 port_edge != NULL;
232 port_edge = port_edge->next)
233 {
234 handler (me, port_edge->my_port,
235 port_edge->dest, port_edge->dest_port,
236 data);
237 }
238}
239
240
241int
242hw_port_decode (struct hw *me,
243 const char *port_name,
244 port_direction direction)
245{
246 if (port_name == NULL || port_name[0] == '\0')
247 return 0;
34b47c38 248 if (isdigit (port_name[0]))
c906108c
SS
249 {
250 return strtoul (port_name, NULL, 0);
251 }
252 else
253 {
254 const struct hw_port_descriptor *ports =
255 me->ports_of_hw->ports;
028f6515 256 if (ports != NULL)
c906108c
SS
257 {
258 while (ports->name != NULL)
259 {
260 if (ports->direction == bidirect_port
261 || ports->direction == direction)
262 {
263 if (ports->nr_ports > 0)
264 {
265 int len = strlen (ports->name);
266 if (strncmp (port_name, ports->name, len) == 0)
267 {
268 if (port_name[len] == '\0')
269 return ports->number;
34b47c38 270 else if (isdigit (port_name[len]))
c906108c
SS
271 {
272 int port = (ports->number
273 + strtoul (&port_name[len], NULL, 0));
274 if (port >= ports->number + ports->nr_ports)
275 hw_abort (me,
276 "Port %s out of range",
277 port_name);
278 return port;
279 }
280 }
281 }
282 else if (strcmp (port_name, ports->name) == 0)
283 return ports->number;
284 }
285 ports++;
286 }
287 }
288 }
ffbc20d9 289 hw_abort (me, "Unrecognized port %s", port_name);
c906108c
SS
290 return 0;
291}
292
293
294int
295hw_port_encode (struct hw *me,
296 int port_number,
297 char *buf,
298 int sizeof_buf,
299 port_direction direction)
300{
301 const struct hw_port_descriptor *ports = NULL;
302 ports = me->ports_of_hw->ports;
303 if (ports != NULL) {
304 while (ports->name != NULL)
305 {
306 if (ports->direction == bidirect_port
307 || ports->direction == direction)
308 {
309 if (ports->nr_ports > 0)
310 {
311 if (port_number >= ports->number
312 && port_number < ports->number + ports->nr_ports)
313 {
314 strcpy (buf, ports->name);
34b47c38 315 sprintf (buf + strlen (buf), "%d", port_number - ports->number);
c906108c
SS
316 if (strlen (buf) >= sizeof_buf)
317 hw_abort (me, "hw_port_encode: buffer overflow");
318 return strlen (buf);
319 }
320 }
321 else
322 {
323 if (ports->number == port_number)
324 {
34b47c38 325 if (strlen (ports->name) >= sizeof_buf)
c906108c 326 hw_abort (me, "hw_port_encode: buffer overflow");
34b47c38
MF
327 strcpy (buf, ports->name);
328 return strlen (buf);
c906108c
SS
329 }
330 }
331 }
332 ports++;
333 }
334 }
335 sprintf (buf, "%d", port_number);
34b47c38 336 if (strlen (buf) >= sizeof_buf)
c906108c 337 hw_abort (me, "hw_port_encode: buffer overflow");
34b47c38 338 return strlen (buf);
c906108c 339}