1 1.1 christos /* Hardware ports. 2 1.1.1.11 christos Copyright (C) 1998-2025 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