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