Home | History | Annotate | Line # | Download | only in common
      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