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