1 /* Simulator hardware option handling.
2 Copyright (C) 1998 Free Software Foundation, Inc.
3 Contributed by Cygnus Support and Andrew Cagney.
5 This file is part of GDB, the GNU debugger.
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 2, or (at your option)
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.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include "sim-assert.h"
23 #include "sim-options.h"
28 #include "hw-device.h"
44 #include <sys/errno.h>
51 /* if called from a processor */
58 sim_hw_parse (struct sim_state
*sd
,
65 current
= hw_tree_vparse (STATE_HW (sd
)->tree
, fmt
, ap
);
71 struct sim_state
*file
;
72 void (*print
) (struct sim_state
*, const char *, va_list ap
);
76 do_print (void *file
, const char *fmt
, ...)
78 struct printer
*p
= file
;
81 p
->print (p
->file
, fmt
, ap
);
86 sim_hw_print (struct sim_state
*sd
,
87 void (*print
) (struct sim_state
*, const char *, va_list ap
))
92 hw_tree_print (STATE_HW (sd
)->tree
, do_print
, &p
);
98 /* command line options. */
101 OPTION_HW_INFO
= OPTION_START
,
107 static DECLARE_OPTION_HANDLER (hw_option_handler
);
109 static const OPTION hw_options
[] =
111 { {"hw-info", no_argument
, NULL
, OPTION_HW_INFO
},
112 '\0', NULL
, "List configurable hw regions",
114 { {"info-hw", no_argument
, NULL
, OPTION_HW_INFO
},
118 { {"hw-trace", optional_argument
, NULL
, OPTION_HW_TRACE
},
119 '\0', "on|off", "Trace all hardware devices",
121 { {"trace-hw", optional_argument
, NULL
, OPTION_HW_TRACE
},
125 { {"hw-device", required_argument
, NULL
, OPTION_HW_DEVICE
},
126 '\0', "DEVICE", "Add the specified device",
129 { {"hw-file", required_argument
, NULL
, OPTION_HW_FILE
},
130 '\0', "FILE", "Add the devices listed in the file",
133 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
138 /* Copied from ../ppc/psim.c:psim_merge_device_file() */
141 merge_device_file (struct sim_state
*sd
,
142 const char *file_name
)
145 struct hw
*current
= STATE_HW (sd
)->tree
;
147 char device_path
[1000];
149 /* try opening the file */
150 description
= fopen (file_name
, "r");
151 if (description
== NULL
)
158 while (fgets (device_path
, sizeof(device_path
), description
))
161 /* check that a complete line was read */
162 if (strchr (device_path
, '\n') == NULL
)
164 fclose (description
);
165 sim_io_eprintf (sd
, "%s:%d: line to long", file_name
, line_nr
);
168 *strchr (device_path
, '\n') = '\0';
170 /* skip comments ("#" or ";") and blank lines lines */
171 for (device
= device_path
;
172 *device
!= '\0' && isspace (*device
);
176 || device
[0] == '\0')
178 /* merge any appended lines */
179 while (device_path
[strlen (device_path
) - 1] == '\\')
181 int curlen
= strlen (device_path
) - 1;
182 /* zap the `\' at the end of the line */
183 device_path
[curlen
] = '\0';
184 /* append the next line */
185 if (!fgets (device_path
+ curlen
,
186 sizeof (device_path
) - curlen
,
189 fclose (description
);
190 sim_io_eprintf (sd
, "%s:%d: unexpected eof", file_name
, line_nr
);
193 if (strchr(device_path
, '\n') == NULL
)
196 sim_io_eprintf (sd
, "%s:%d: line to long", file_name
, line_nr
);
199 *strchr(device_path
, '\n') = '\0';
202 /* parse this line */
203 current
= hw_tree_parse (current
, "%s", device
);
205 fclose (description
);
211 hw_option_handler (struct sim_state
*sd
, sim_cpu
*cpu
, int opt
,
212 char *arg
, int is_command
)
219 /* delay info until after the tree is finished */
220 STATE_HW (sd
)->info_p
= 1;
225 case OPTION_HW_TRACE
:
229 STATE_HW (sd
)->trace_p
= 1;
231 else if (strcmp (arg
, "yes") == 0
232 || strcmp (arg
, "on") == 0)
234 STATE_HW (sd
)->trace_p
= 1;
236 else if (strcmp (arg
, "no") == 0
237 || strcmp (arg
, "off") == 0)
239 STATE_HW (sd
)->trace_p
= 0;
243 sim_io_eprintf (sd
, "Option --hw-trace ignored\n");
244 /* set tracing on all devices */
247 /* FIXME: Not very nice - see also hw-base.c */
248 if (STATE_HW (sd
)->trace_p
)
249 hw_tree_parse (STATE_HW (sd
)->tree
, "/global-trace? true");
254 case OPTION_HW_DEVICE
:
256 hw_tree_parse (STATE_HW (sd
)->tree
, arg
);
262 return merge_device_file (sd
, arg
);
266 sim_io_eprintf (sd
, "Unknown hw option %d\n", opt
);
275 /* "hw" module install handler.
277 This is called via sim_module_install to install the "hw" subsystem
278 into the simulator. */
280 static MODULE_INIT_FN sim_hw_init
;
281 static MODULE_UNINSTALL_FN sim_hw_uninstall
;
284 sim_hw_install (struct sim_state
*sd
)
286 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
287 sim_add_option_table (sd
, NULL
, hw_options
);
288 sim_module_add_uninstall_fn (sd
, sim_hw_uninstall
);
289 sim_module_add_init_fn (sd
, sim_hw_init
);
290 STATE_HW (sd
) = ZALLOC (struct sim_hw
);
291 STATE_HW (sd
)->tree
= hw_tree_create (sd
, "core");
297 sim_hw_init (struct sim_state
*sd
)
299 /* FIXME: anything needed? */
300 hw_tree_finish (STATE_HW (sd
)->tree
);
301 if (STATE_HW (sd
)->info_p
)
302 sim_hw_print (sd
, sim_io_vprintf
);
306 /* Uninstall the "hw" subsystem from the simulator. */
309 sim_hw_uninstall (struct sim_state
*sd
)
311 /* hw_tree_delete (STATE_HW (sd)->tree); */
312 zfree (STATE_HW (sd
));
313 STATE_HW (sd
) = NULL
;
318 /* Data transfers to/from the hardware device tree. There are several
322 /* CPU: The simulation is running and the current CPU/CIA
323 initiates a data transfer. */
326 sim_cpu_hw_io_read_buffer (sim_cpu
*cpu
,
334 SIM_DESC sd
= CPU_STATE (cpu
);
335 STATE_HW (sd
)->cpu
= cpu
;
336 STATE_HW (sd
)->cia
= cia
;
337 if (hw_io_read_buffer (hw
, dest
, space
, addr
, nr_bytes
) != nr_bytes
)
338 sim_engine_abort (sd
, cpu
, cia
, "broken CPU read");
342 sim_cpu_hw_io_write_buffer (sim_cpu
*cpu
,
350 SIM_DESC sd
= CPU_STATE (cpu
);
351 STATE_HW (sd
)->cpu
= cpu
;
352 STATE_HW (sd
)->cia
= cia
;
353 if (hw_io_write_buffer (hw
, source
, space
, addr
, nr_bytes
) != nr_bytes
)
354 sim_engine_abort (sd
, cpu
, cia
, "broken CPU write");
360 /* SYSTEM: A data transfer is being initiated by the system. */
363 sim_hw_io_read_buffer (struct sim_state
*sd
,
370 STATE_HW (sd
)->cpu
= NULL
;
371 return hw_io_read_buffer (hw
, dest
, space
, addr
, nr_bytes
);
375 sim_hw_io_write_buffer (struct sim_state
*sd
,
382 STATE_HW (sd
)->cpu
= NULL
;
383 return hw_io_write_buffer (hw
, source
, space
, addr
, nr_bytes
);
388 /* Abort the simulation specifying HW as the reason */
391 hw_vabort (struct hw
*me
,
397 /* find an identity */
398 if (me
!= NULL
&& hw_path (me
) != NULL
&& hw_path (me
) [0] != '\0')
400 else if (me
!= NULL
&& hw_name (me
) != NULL
&& hw_name (me
)[0] != '\0')
402 else if (me
!= NULL
&& hw_family (me
) != NULL
&& hw_family (me
)[0] != '\0')
403 name
= hw_family (me
);
406 /* construct an updated format string */
407 msg
= alloca (strlen (name
) + strlen (": ") + strlen (fmt
) + 1);
411 /* report the problem */
412 sim_engine_vabort (hw_system (me
),
413 STATE_HW (hw_system (me
))->cpu
,
414 STATE_HW (hw_system (me
))->cia
,
419 hw_abort (struct hw
*me
,
424 /* report the problem */
426 hw_vabort (me
, fmt
, ap
);
431 sim_hw_abort (struct sim_state
*sd
,
439 sim_engine_vabort (sd
, NULL
, NULL_CIA
, fmt
, ap
);
441 hw_vabort (me
, fmt
, ap
);
446 /* MISC routines to tie HW into the rest of the system */
449 hw_halt (struct hw
*me
,
453 struct sim_state
*sd
= hw_system (me
);
454 struct sim_hw
*sim
= STATE_HW (sd
);
455 sim_engine_halt (sd
, sim
->cpu
, NULL
, sim
->cia
, reason
, status
);
459 hw_system_cpu (struct hw
*me
)
461 return STATE_HW (hw_system (me
))->cpu
;
465 hw_trace (struct hw
*me
,
469 if (hw_trace_p (me
)) /* to be sure, to be sure */
473 sim_io_eprintf (hw_system (me
), "%s: ", hw_path (me
));
474 sim_io_evprintf (hw_system (me
), fmt
, ap
);
475 sim_io_eprintf (hw_system (me
), "\n");
481 /* Based on gdb-4.17/sim/ppc/main.c:sim_io_read_stdin() */
484 do_hw_poll_read (struct hw
*me
,
485 do_hw_poll_read_method
*read
,
490 int status
= read (hw_system (me
), sim_io_fd
, buf
, sizeof_buf
);
493 else if (status
== 0 && sizeof_buf
== 0)
495 else if (status
== 0)
497 else /* status < 0 */
500 if (STATE_CALLBACK (hw_system (me
))->last_errno
== EAGAIN
)
501 return HW_IO_NOT_READY
;