OSDN Git Service

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