Based on patches from H.J. Lu <hjl@nynexst.com>:
[deliverable/binutils-gdb.git] / gdb / remote-nindy.c
CommitLineData
dd3b648e 1/* Memory-access and commands for remote NINDY process, for GDB.
58bcc08c 2 Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
dd3b648e
RP
3 Contributed by Intel Corporation. Modified from remote.c by Chris Benenati.
4
5GDB is distributed in the hope that it will be useful, but WITHOUT ANY
6WARRANTY. No author or distributor accepts responsibility to anyone
7for the consequences of using it or for whether it serves any
8particular purpose or works at all, unless he says so in writing.
9Refer to the GDB General Public License for full details.
10
11Everyone is granted permission to copy, modify and redistribute GDB,
12but only under the conditions described in the GDB General Public
13License. A copy of this license is supposed to have been given to you
14along with GDB so you can know your rights and responsibilities. It
15should be in a file named COPYING. Among other things, the copyright
16notice and this notice must be preserved on all copies.
17
18In other words, go ahead and share GDB, but don't try to stop
19anyone else from sharing it farther. Help stamp out software hoarding!
20*/
21
22/*
23Except for the data cache routines, this file bears little resemblence
24to remote.c. A new (although similar) protocol has been specified, and
25portions of the code are entirely dependent on having an i80960 with a
26NINDY ROM monitor at the other end of the line.
27*/
28
29/*****************************************************************************
30 *
31 * REMOTE COMMUNICATION PROTOCOL BETWEEN GDB960 AND THE NINDY ROM MONITOR.
32 *
33 *
34 * MODES OF OPERATION
35 * ----- -- ---------
36 *
37 * As far as NINDY is concerned, GDB is always in one of two modes: command
38 * mode or passthrough mode.
39 *
40 * In command mode (the default) pre-defined packets containing requests
41 * are sent by GDB to NINDY. NINDY never talks except in reponse to a request.
42 *
43 * Once the the user program is started, GDB enters passthrough mode, to give
44 * the user program access to the terminal. GDB remains in this mode until
45 * NINDY indicates that the program has stopped.
46 *
47 *
48 * PASSTHROUGH MODE
49 * ----------- ----
50 *
51 * GDB writes all input received from the keyboard directly to NINDY, and writes
52 * all characters received from NINDY directly to the monitor.
53 *
54 * Keyboard input is neither buffered nor echoed to the monitor.
55 *
56 * GDB remains in passthrough mode until NINDY sends a single ^P character,
57 * to indicate that the user process has stopped.
58 *
59 * Note:
60 * GDB assumes NINDY performs a 'flushreg' when the user program stops.
61 *
62 *
63 * COMMAND MODE
64 * ------- ----
65 *
66 * All info (except for message ack and nak) is transferred between gdb
67 * and the remote processor in messages of the following format:
68 *
69 * <info>#<checksum>
70 *
71 * where
72 * # is a literal character
73 *
74 * <info> ASCII information; all numeric information is in the
75 * form of hex digits ('0'-'9' and lowercase 'a'-'f').
76 *
77 * <checksum>
78 * is a pair of ASCII hex digits representing an 8-bit
79 * checksum formed by adding together each of the
80 * characters in <info>.
81 *
82 * The receiver of a message always sends a single character to the sender
83 * to indicate that the checksum was good ('+') or bad ('-'); the sender
84 * re-transmits the entire message over until a '+' is received.
85 *
86 * In response to a command NINDY always sends back either data or
87 * a result code of the form "Xnn", where "nn" are hex digits and "X00"
88 * means no errors. (Exceptions: the "s" and "c" commands don't respond.)
89 *
90 * SEE THE HEADER OF THE FILE "gdb.c" IN THE NINDY MONITOR SOURCE CODE FOR A
91 * FULL DESCRIPTION OF LEGAL COMMANDS.
92 *
93 * SEE THE FILE "stop.h" IN THE NINDY MONITOR SOURCE CODE FOR A LIST
94 * OF STOP CODES.
95 *
6ecb870e 96 ***************************************************************************/
dd3b648e 97
d747e0af 98#include "defs.h"
dd3b648e
RP
99#include <signal.h>
100#include <sys/types.h>
101#include <setjmp.h>
102
dd3b648e
RP
103#include "frame.h"
104#include "inferior.h"
77641260 105#include "bfd.h"
6b27ebe8 106#include "symfile.h"
dd3b648e
RP
107#include "target.h"
108#include "gdbcore.h"
109#include "command.h"
48792545 110#include "floatformat.h"
dd3b648e
RP
111
112#include "wait.h"
dd3b648e
RP
113#include <sys/file.h>
114#include <ctype.h>
704deef2 115#include "serial.h"
dd3b648e
RP
116#include "nindy-share/env.h"
117#include "nindy-share/stop.h"
118
5a0a463f 119#include "dcache.h"
a94abe5b 120#include "remote-utils.h"
5a0a463f
RP
121
122static DCACHE *nindy_dcache;
123
dd3b648e
RP
124extern int unlink();
125extern char *getenv();
126extern char *mktemp();
127
dd3b648e
RP
128extern void generic_mourn_inferior ();
129
130extern struct target_ops nindy_ops;
199b2450 131extern GDB_FILE *instream;
dd3b648e
RP
132
133extern char ninStopWhy ();
6deb63ab
JK
134extern int ninMemGet ();
135extern int ninMemPut ();
dd3b648e
RP
136
137int nindy_initial_brk; /* nonzero if want to send an initial BREAK to nindy */
138int nindy_old_protocol; /* nonzero if want to use old protocol */
139char *nindy_ttyname; /* name of tty to talk to nindy on, or null */
140
141#define DLE '\020' /* Character NINDY sends to indicate user program has
142 * halted. */
143#define TRUE 1
144#define FALSE 0
145
704deef2
JK
146/* From nindy-share/nindy.c. */
147extern serial_t nindy_serial;
148
dd3b648e
RP
149static int have_regs = 0; /* 1 iff regs read since i960 last halted */
150static int regs_changed = 0; /* 1 iff regs were modified since last read */
151
152extern char *exists();
e4db3f3e 153
e4db3f3e
JG
154static void
155nindy_fetch_registers PARAMS ((int));
156
157static void
158nindy_store_registers PARAMS ((int));
dd3b648e 159\f
dd3b648e
RP
160static char *savename;
161
162static void
163nindy_close (quitting)
164 int quitting;
165{
704deef2
JK
166 if (nindy_serial != NULL)
167 SERIAL_CLOSE (nindy_serial);
168 nindy_serial = NULL;
dd3b648e
RP
169
170 if (savename)
171 free (savename);
172 savename = 0;
173}
174
175/* Open a connection to a remote debugger.
b10f4dd9
JK
176 FIXME, there should be "set" commands for the options that are
177 now specified with gdb command-line options (old_protocol,
178 and initial_brk). */
dd3b648e
RP
179void
180nindy_open (name, from_tty)
181 char *name; /* "/dev/ttyXX", "ttyXX", or "XX": tty to be opened */
182 int from_tty;
183{
a94abe5b 184 char baudrate[1024];
dd3b648e
RP
185
186 if (!name)
187 error_no_arg ("serial port device name");
188
f2fc6e7a 189 target_preopen (from_tty);
b10f4dd9 190
dd3b648e
RP
191 nindy_close (0);
192
704deef2 193 have_regs = regs_changed = 0;
5a0a463f 194 nindy_dcache = dcache_init(ninMemGet, ninMemPut);
dd3b648e 195
704deef2
JK
196 /* Allow user to interrupt the following -- we could hang if there's
197 no NINDY at the other end of the remote tty. */
198 immediate_quit++;
c20c1bdf
JK
199 /* If baud_rate is -1, then ninConnect will not recognize the baud rate
200 and will deal with the situation in a (more or less) reasonable
201 fashion. */
202 sprintf(baudrate, "%d", baud_rate);
a94abe5b 203 ninConnect(name, baudrate,
704deef2
JK
204 nindy_initial_brk, !from_tty, nindy_old_protocol);
205 immediate_quit--;
dd3b648e 206
704deef2
JK
207 if (nindy_serial == NULL)
208 {
209 perror_with_name (name);
210 }
dd3b648e 211
704deef2
JK
212 savename = savestring (name, strlen (name));
213 push_target (&nindy_ops);
214 target_fetch_registers(-1);
dd3b648e
RP
215}
216
217/* User-initiated quit of nindy operations. */
218
219static void
220nindy_detach (name, from_tty)
221 char *name;
222 int from_tty;
223{
dd3b648e
RP
224 if (name)
225 error ("Too many arguments");
226 pop_target ();
227}
228
229static void
230nindy_files_info ()
231{
c20c1bdf
JK
232 /* FIXME: this lies about the baud rate if we autobauded. */
233 printf_unfiltered("\tAttached to %s at %d bits per second%s%s.\n", savename,
234 baud_rate,
dd3b648e
RP
235 nindy_old_protocol? " in old protocol": "",
236 nindy_initial_brk? " with initial break": "");
237}
238\f
6b27ebe8
JK
239/* Return the number of characters in the buffer before
240 the first DLE character. */
dd3b648e
RP
241
242static
243int
244non_dle( buf, n )
245 char *buf; /* Character buffer; NOT '\0'-terminated */
246 int n; /* Number of characters in buffer */
247{
248 int i;
249
250 for ( i = 0; i < n; i++ ){
251 if ( buf[i] == DLE ){
252 break;
253 }
254 }
255 return i;
256}
257\f
258/* Tell the remote machine to resume. */
259
260void
25286543 261nindy_resume (pid, step, siggnal)
67ac9759
JK
262 int pid, step;
263 enum target_signal siggnal;
dd3b648e 264{
67ac9759
JK
265 if (siggnal != TARGET_SIGNAL_0 && siggnal != stop_signal)
266 warning ("Can't send signals to remote NINDY targets.");
dd3b648e 267
5a0a463f 268 dcache_flush(nindy_dcache);
dd3b648e 269 if ( regs_changed ){
df86eb44 270 nindy_store_registers (-1);
dd3b648e
RP
271 regs_changed = 0;
272 }
273 have_regs = 0;
274 ninGo( step );
275}
704deef2
JK
276\f
277/* FIXME, we can probably use the normal terminal_inferior stuff here.
278 We have to do terminal_inferior and then set up the passthrough
279 settings initially. Thereafter, terminal_ours and terminal_inferior
280 will automatically swap the settings around for us. */
281
282struct clean_up_tty_args {
283 serial_ttystate state;
284 serial_t serial;
285};
cac390d4 286static struct clean_up_tty_args tty_args;
704deef2
JK
287
288static void
289clean_up_tty (ptrarg)
290 PTR ptrarg;
291{
292 struct clean_up_tty_args *args = (struct clean_up_tty_args *) ptrarg;
293 SERIAL_SET_TTY_STATE (args->serial, args->state);
294 free (args->state);
cac390d4
SG
295 warning ("\n\nYou may need to reset the 80960 and/or reload your program.\n");
296}
297
298/* Recover from ^Z or ^C while remote process is running */
299static void (*old_ctrlc)();
300#ifdef SIGTSTP
301static void (*old_ctrlz)();
302#endif
303
304static void
305clean_up_int()
306{
307 SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
308 free (tty_args.state);
309
310 signal(SIGINT, old_ctrlc);
311#ifdef SIGTSTP
312 signal(SIGTSTP, old_ctrlz);
313#endif
314 error("\n\nYou may need to reset the 80960 and/or reload your program.\n");
704deef2 315}
dd3b648e
RP
316
317/* Wait until the remote machine stops. While waiting, operate in passthrough
199b2450 318 * mode; i.e., pass everything NINDY sends to gdb_stdout, and everything from
dd3b648e
RP
319 * stdin to NINDY.
320 *
321 * Return to caller, storing status in 'status' just as `wait' would.
322 */
323
e4db3f3e 324static int
de43d7d0
SG
325nindy_wait( pid, status )
326 int pid;
67ac9759 327 struct target_waitstatus *status;
dd3b648e 328{
704deef2 329 fd_set fds;
cac390d4
SG
330 int c;
331 char buf[2];
704deef2
JK
332 int i, n;
333 unsigned char stop_exit;
334 unsigned char stop_code;
704deef2
JK
335 struct cleanup *old_cleanups;
336 long ip_value, fp_value, sp_value; /* Reg values from stop */
337
67ac9759
JK
338 status->kind = TARGET_WAITKIND_EXITED;
339 status->value.integer = 0;
704deef2
JK
340
341 /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
342
343 /* Save current tty attributes, and restore them when done. */
344 tty_args.serial = SERIAL_FDOPEN (0);
345 tty_args.state = SERIAL_GET_TTY_STATE (tty_args.serial);
cac390d4
SG
346 old_ctrlc = signal( SIGINT, clean_up_int );
347#ifdef SIGTSTP
348 old_ctrlz = signal( SIGTSTP, clean_up_int );
349#endif
350
704deef2
JK
351 old_cleanups = make_cleanup (clean_up_tty, &tty_args);
352
353 /* Pass input from keyboard to NINDY as it arrives. NINDY will interpret
354 <CR> and perform echo. */
355 /* This used to set CBREAK and clear ECHO and CRMOD. I hope this is close
356 enough. */
357 SERIAL_RAW (tty_args.serial);
358
359 while (1)
360 {
cac390d4 361 /* Input on remote */
89fd75ae 362 c = SERIAL_READCHAR (nindy_serial, -1);
cac390d4 363 if (c == SERIAL_ERROR)
704deef2 364 {
cac390d4 365 error ("Cannot read from serial line");
704deef2 366 }
cac390d4
SG
367 else if (c == 0x1b) /* ESC */
368 {
c6236d12 369 c = SERIAL_READCHAR (nindy_serial, -1);
cac390d4
SG
370 c &= ~0x40;
371 }
372 else if (c != 0x10) /* DLE */
373 /* Write out any characters preceding DLE */
374 {
375 buf[0] = (char)c;
376 write (1, buf, 1);
377 }
378 else
704deef2 379 {
704deef2
JK
380 stop_exit = ninStopWhy(&stop_code,
381 &ip_value, &fp_value, &sp_value);
382 if (!stop_exit && (stop_code == STOP_SRQ))
383 {
384 immediate_quit++;
385 ninSrq();
386 immediate_quit--;
387 }
388 else
389 {
390 /* Get out of loop */
391 supply_register (IP_REGNUM,
392 (char *)&ip_value);
393 supply_register (FP_REGNUM,
394 (char *)&fp_value);
395 supply_register (SP_REGNUM,
396 (char *)&sp_value);
397 break;
398 }
704deef2 399 }
704deef2 400 }
dd3b648e 401
cac390d4
SG
402 SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
403 free (tty_args.state);
404 discard_cleanups (old_cleanups);
704deef2
JK
405
406 if (stop_exit)
407 {
67ac9759
JK
408 status->kind = TARGET_WAITKIND_EXITED;
409 status->value.integer = stop_code;
704deef2
JK
410 }
411 else
412 {
cac390d4
SG
413 /* nindy has some special stop code need to be handled */
414 if (stop_code == STOP_GDB_BPT)
415 stop_code = TRACE_STEP;
67ac9759
JK
416 status->kind = TARGET_WAITKIND_STOPPED;
417 status->value.sig = i960_fault_to_signal (stop_code);
704deef2
JK
418 }
419 return inferior_pid;
dd3b648e
RP
420}
421
422/* Read the remote registers into the block REGS. */
423
424/* This is the block that ninRegsGet and ninRegsPut handles. */
425struct nindy_regs {
426 char local_regs[16 * 4];
427 char global_regs[16 * 4];
428 char pcw_acw[2 * 4];
429 char ip[4];
430 char tcw[4];
431 char fp_as_double[4 * 8];
432};
433
120f867e 434static void
dd3b648e
RP
435nindy_fetch_registers(regno)
436 int regno;
437{
438 struct nindy_regs nindy_regs;
439 int regnum, inv;
440 double dub;
441
442 immediate_quit++;
443 ninRegsGet( (char *) &nindy_regs );
444 immediate_quit--;
445
704deef2
JK
446 memcpy (&registers[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16*4);
447 memcpy (&registers[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4);
448 memcpy (&registers[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2*4);
449 memcpy (&registers[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1*4);
450 memcpy (&registers[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 1*4);
dd3b648e
RP
451 for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
452 dub = unpack_double (builtin_type_double,
453 &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
454 &inv);
455 /* dub now in host byte order */
48792545 456 floatformat_from_double (&floatformat_i960_ext, &dub,
dd3b648e
RP
457 &registers[REGISTER_BYTE (regnum)]);
458 }
459
460 registers_fetched ();
dd3b648e
RP
461}
462
463static void
464nindy_prepare_to_store()
465{
4ddd278f
JG
466 /* Fetch all regs if they aren't already here. */
467 read_register_bytes (0, NULL, REGISTER_BYTES);
dd3b648e
RP
468}
469
120f867e 470static void
dd3b648e
RP
471nindy_store_registers(regno)
472 int regno;
473{
474 struct nindy_regs nindy_regs;
bf5c0d64 475 int regnum;
dd3b648e
RP
476 double dub;
477
704deef2
JK
478 memcpy (nindy_regs.local_regs, &registers[REGISTER_BYTE (R0_REGNUM)], 16*4);
479 memcpy (nindy_regs.global_regs, &registers[REGISTER_BYTE (G0_REGNUM)], 16*4);
480 memcpy (nindy_regs.pcw_acw, &registers[REGISTER_BYTE (PCW_REGNUM)], 2*4);
481 memcpy (nindy_regs.ip, &registers[REGISTER_BYTE (IP_REGNUM)], 1*4);
482 memcpy (nindy_regs.tcw, &registers[REGISTER_BYTE (TCW_REGNUM)], 1*4);
bf5c0d64
JK
483 for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++)
484 {
48792545
JK
485 floatformat_to_double (&floatformat_i960_ext,
486 &registers[REGISTER_BYTE (regnum)], &dub);
bf5c0d64
JK
487 store_floating (&nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
488 REGISTER_VIRTUAL_SIZE (regnum),
489 dub);
490 }
dd3b648e
RP
491
492 immediate_quit++;
493 ninRegsPut( (char *) &nindy_regs );
494 immediate_quit--;
dd3b648e
RP
495}
496
497/* Read a word from remote address ADDR and return it.
498 * This goes through the data cache.
499 */
500int
501nindy_fetch_word (addr)
502 CORE_ADDR addr;
503{
5a0a463f 504 return dcache_fetch (nindy_dcache, addr);
dd3b648e
RP
505}
506
507/* Write a word WORD into remote address ADDR.
508 This goes through the data cache. */
509
510void
511nindy_store_word (addr, word)
512 CORE_ADDR addr;
513 int word;
514{
5a0a463f 515 dcache_poke (nindy_dcache, addr, word);
dd3b648e
RP
516}
517
518/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
519 to debugger memory starting at MYADDR. Copy to inferior if
520 WRITE is nonzero. Returns the length copied.
521
522 This is stolen almost directly from infptrace.c's child_xfer_memory,
523 which also deals with a word-oriented memory interface. Sometime,
524 FIXME, rewrite this to not use the word-oriented routines. */
525
526int
8f1f2a72 527nindy_xfer_inferior_memory(memaddr, myaddr, len, write, target)
dd3b648e
RP
528 CORE_ADDR memaddr;
529 char *myaddr;
530 int len;
531 int write;
8f1f2a72 532 struct target_ops *target; /* ignored */
dd3b648e
RP
533{
534 register int i;
535 /* Round starting address down to longword boundary. */
536 register CORE_ADDR addr = memaddr & - sizeof (int);
537 /* Round ending address up; get number of longwords that makes. */
538 register int count
539 = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
540 /* Allocate buffer of that many longwords. */
541 register int *buffer = (int *) alloca (count * sizeof (int));
542
543 if (write)
544 {
545 /* Fill start and end extra bytes of buffer with existing memory data. */
546
547 if (addr != memaddr || len < (int)sizeof (int)) {
548 /* Need part of initial word -- fetch it. */
549 buffer[0] = nindy_fetch_word (addr);
550 }
551
552 if (count > 1) /* FIXME, avoid if even boundary */
553 {
554 buffer[count - 1]
555 = nindy_fetch_word (addr + (count - 1) * sizeof (int));
556 }
557
558 /* Copy data to be written over corresponding part of buffer */
559
704deef2 560 memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
dd3b648e
RP
561
562 /* Write the entire buffer. */
563
564 for (i = 0; i < count; i++, addr += sizeof (int))
565 {
566 errno = 0;
567 nindy_store_word (addr, buffer[i]);
568 if (errno)
569 return 0;
570 }
571 }
572 else
573 {
574 /* Read all the longwords */
575 for (i = 0; i < count; i++, addr += sizeof (int))
576 {
577 errno = 0;
578 buffer[i] = nindy_fetch_word (addr);
579 if (errno)
580 return 0;
581 QUIT;
582 }
583
584 /* Copy appropriate bytes out of the buffer. */
704deef2 585 memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
dd3b648e
RP
586 }
587 return len;
588}
589\f
dd3b648e
RP
590static void
591nindy_create_inferior (execfile, args, env)
592 char *execfile;
593 char *args;
594 char **env;
595{
596 int entry_pt;
597 int pid;
598
599 if (args && *args)
600 error ("Can't pass arguments to remote NINDY process");
601
602 if (execfile == 0 || exec_bfd == 0)
603 error ("No exec file specified");
604
605 entry_pt = (int) bfd_get_start_address (exec_bfd);
606
607 pid = 42;
608
5d76c8e6
JK
609 /* The "process" (board) is already stopped awaiting our commands, and
610 the program is already downloaded. We just set its PC and go. */
dd3b648e
RP
611
612 inferior_pid = pid; /* Needed for wait_for_inferior below */
613
614 clear_proceed_status ();
615
dd3b648e
RP
616 /* Tell wait_for_inferior that we've started a new process. */
617 init_wait_for_inferior ();
618
619 /* Set up the "saved terminal modes" of the inferior
620 based on what modes we are starting it with. */
621 target_terminal_init ();
622
623 /* Install inferior's terminal modes. */
624 target_terminal_inferior ();
625
dd3b648e 626 /* insert_step_breakpoint (); FIXME, do we need this? */
45dc9be3
JK
627 /* Let 'er rip... */
628 proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
dd3b648e
RP
629}
630
631static void
632reset_command(args, from_tty)
633 char *args;
634 int from_tty;
635{
704deef2
JK
636 if (nindy_serial == NULL)
637 {
638 error( "No target system to reset -- use 'target nindy' command.");
639 }
640 if ( query("Really reset the target system?",0,0) )
641 {
642 SERIAL_SEND_BREAK (nindy_serial);
643 tty_flush (nindy_serial);
644 }
dd3b648e
RP
645}
646
647void
648nindy_kill (args, from_tty)
649 char *args;
650 int from_tty;
651{
652 return; /* Ignore attempts to kill target system */
653}
654
655/* Clean up when a program exits.
656
657 The program actually lives on in the remote processor's RAM, and may be
658 run again without a download. Don't leave it full of breakpoint
659 instructions. */
660
661void
662nindy_mourn_inferior ()
663{
664 remove_breakpoints ();
71607f9d 665 unpush_target (&nindy_ops);
dd3b648e
RP
666 generic_mourn_inferior (); /* Do all the proper things now */
667}
668\f
9748446f
JK
669/* Pass the args the way catch_errors wants them. */
670static int
671nindy_open_stub (arg)
672 char *arg;
673{
674 nindy_open (arg, 1);
675 return 1;
676}
677
8a7143f4
KH
678static void
679nindy_load( filename, from_tty )
680 char *filename;
681 int from_tty;
682{
683 asection *s;
684 /* Can't do unix style forking on a VMS system, so we'll use bfd to do
685 all the work for us
686 */
687
688 bfd *file = bfd_openr(filename,0);
689 if (!file)
690 {
691 perror_with_name(filename);
692 return;
693 }
694
695 if (!bfd_check_format(file, bfd_object))
696 {
697 error("can't prove it's an object file\n");
698 return;
699 }
700
701 for ( s = file->sections; s; s=s->next)
702 {
703 if (s->flags & SEC_LOAD)
704 {
705 char *buffer = xmalloc(s->_raw_size);
706 bfd_get_section_contents(file, s, buffer, 0, s->_raw_size);
707 printf("Loading section %s, size %x vma %x\n",
708 s->name,
709 s->_raw_size,
710 s->vma);
711 ninMemPut(s->vma, buffer, s->_raw_size);
712 free(buffer);
713 }
714 }
715 bfd_close(file);
716}
717
9748446f
JK
718static int
719load_stub (arg)
720 char *arg;
721{
722 target_load (arg, 1);
723 return 1;
724}
725
dd3b648e
RP
726/* This routine is run as a hook, just before the main command loop is
727 entered. If gdb is configured for the i960, but has not had its
728 nindy target specified yet, this will loop prompting the user to do so.
729
730 Unlike the loop provided by Intel, we actually let the user get out
731 of this with a RETURN. This is useful when e.g. simply examining
732 an i960 object file on the host system. */
733
df86eb44 734void
dd3b648e
RP
735nindy_before_main_loop ()
736{
737 char ttyname[100];
738 char *p, *p2;
739
cad1498f
SG
740 while (target_stack->target_ops != &nindy_ops) /* What is this crap??? */
741 { /* remote tty not specified yet */
dd3b648e 742 if ( instream == stdin ){
199b2450
TL
743 printf_unfiltered("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit: ");
744 gdb_flush( gdb_stdout );
dd3b648e
RP
745 }
746 fgets( ttyname, sizeof(ttyname)-1, stdin );
747
748 /* Strip leading and trailing whitespace */
749 for ( p = ttyname; isspace(*p); p++ ){
750 ;
751 }
752 if ( *p == '\0' ){
753 return; /* User just hit spaces or return, wants out */
754 }
755 for ( p2= p; !isspace(*p2) && (*p2 != '\0'); p2++ ){
756 ;
757 }
758 *p2= '\0';
2e4964ad 759 if ( STREQ("quit",p) ){
dd3b648e
RP
760 exit(1);
761 }
762
9748446f
JK
763 if (catch_errors (nindy_open_stub, p, "", RETURN_MASK_ALL))
764 {
765 /* Now that we have a tty open for talking to the remote machine,
766 download the executable file if one was specified. */
767 if (exec_bfd)
768 {
769 catch_errors (load_stub, bfd_get_filename (exec_bfd), "",
770 RETURN_MASK_ALL);
771 }
772 }
dd3b648e
RP
773 }
774}
775\f
776/* Define the target subroutine names */
777
778struct target_ops nindy_ops = {
779 "nindy", "Remote serial target in i960 NINDY-specific protocol",
f2fc6e7a
JK
780 "Use a remote i960 system running NINDY connected by a serial line.\n\
781Specify the name of the device the serial line is connected to.\n\
782The speed (baud rate), whether to use the old NINDY protocol,\n\
783and whether to send a break on startup, are controlled by options\n\
784specified when you started GDB.",
dd3b648e 785 nindy_open, nindy_close,
58bcc08c
JG
786 0,
787 nindy_detach,
788 nindy_resume,
789 nindy_wait,
dd3b648e 790 nindy_fetch_registers, nindy_store_registers,
a03d4f8e 791 nindy_prepare_to_store,
dd3b648e 792 nindy_xfer_inferior_memory, nindy_files_info,
771d7a99
SC
793 memory_insert_breakpoint,
794 memory_remove_breakpoint,
dd3b648e
RP
795 0, 0, 0, 0, 0, /* Terminal crud */
796 nindy_kill,
8a7143f4 797 nindy_load,
dd3b648e
RP
798 0, /* lookup_symbol */
799 nindy_create_inferior,
800 nindy_mourn_inferior,
0256270d
KR
801 0, /* can_run */
802 0, /* notice_signals */
78b459a7 803 0, /* to_stop */
dd3b648e
RP
804 process_stratum, 0, /* next */
805 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
8f1f2a72 806 0, 0, /* Section pointers */
dd3b648e
RP
807 OPS_MAGIC, /* Always the last thing */
808};
809
810void
811_initialize_nindy ()
812{
813 add_target (&nindy_ops);
814 add_com ("reset", class_obscure, reset_command,
815 "Send a 'break' to the remote target system.\n\
816Only useful if the target has been equipped with a circuit\n\
817to perform a hard reset when a break is detected.");
818}
This page took 0.254822 seconds and 4 git commands to generate.