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