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