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