]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/hw-ports.c
sim: common: trim trailing whitespace
[thirdparty/binutils-gdb.git] / sim / common / hw-ports.c
1 /* Hardware ports.
2 Copyright (C) 1998, 2007, 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc.
4 Contributed by Andrew Cagney and Cygnus Solutions.
5
6 This file is part of GDB, the GNU debugger.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
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
39
40 struct 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
48 struct 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
54 const struct hw_port_descriptor empty_hw_ports[] = {
55 { NULL, 0, 0, 0 },
56 };
57
58 static void
59 panic_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
68 void
69 create_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
76 void
77 delete_hw_port_data (struct hw *me)
78 {
79 hw_free (me, me->ports_of_hw);
80 me->ports_of_hw = NULL;
81 }
82
83 void
84 set_hw_ports (struct hw *me,
85 const struct hw_port_descriptor ports[])
86 {
87 me->ports_of_hw->ports = ports;
88 }
89
90 void
91 set_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
98 static void
99 attach_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
116 static void
117 detach_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
142 static void
143 clean_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
165 void
166 hw_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
192 void
193 hw_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
208 void
209 hw_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
222 void
223 hw_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
239 int
240 hw_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
292 int
293 hw_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 }