OSDN Git Service

Update the copyright notice of some of the files I missed
[pf3gnuchains/pf3gnuchains3x.git] / sim / common / hw-ports.c
1 /* Hardware ports.
2    Copyright (C) 1998, 2007, 2008, 2009 Free Software Foundation, Inc.
3    Contributed by Andrew Cagney and Cygnus Solutions.
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along 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
41 struct 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
49 struct 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
55 const struct hw_port_descriptor empty_hw_ports[] = {
56   { NULL, },
57 };
58
59 static void
60 panic_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
69 void
70 create_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
77 void
78 delete_hw_port_data (struct hw *me)
79 {
80   hw_free (me, me->ports_of_hw);
81   me->ports_of_hw = NULL;
82 }
83
84 void
85 set_hw_ports (struct hw *me,
86               const struct hw_port_descriptor ports[])
87 {
88   me->ports_of_hw->ports = ports;
89 }
90
91 void
92 set_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
99 static void
100 attach_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
117 static void
118 detach_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
143 static void
144 clean_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
166 void
167 hw_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
193 void
194 hw_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
209 void
210 hw_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
223 void
224 hw_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
240 int
241 hw_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
293 int
294 hw_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 }