Thu Oct 26 10:23:14 1995 steve chamberlain <sac@slash.cygnus.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{
9b73a467 248 int i;
dd3b648e 249
9b73a467
KH
250 for ( i = 0; i < n; i++ ){
251 if ( buf[i] == DLE ){
252 break;
253 }
254 }
255 return i;
dd3b648e
RP
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
9b73a467
KH
268 dcache_flush(nindy_dcache);
269 if ( regs_changed )
270 {
271 nindy_store_registers (-1);
272 regs_changed = 0;
273 }
274 have_regs = 0;
275 ninGo( step );
dd3b648e 276}
704deef2
JK
277\f
278/* FIXME, we can probably use the normal terminal_inferior stuff here.
279 We have to do terminal_inferior and then set up the passthrough
280 settings initially. Thereafter, terminal_ours and terminal_inferior
281 will automatically swap the settings around for us. */
282
283struct clean_up_tty_args {
284 serial_ttystate state;
285 serial_t serial;
286};
cac390d4 287static struct clean_up_tty_args tty_args;
704deef2
JK
288
289static void
290clean_up_tty (ptrarg)
291 PTR ptrarg;
292{
293 struct clean_up_tty_args *args = (struct clean_up_tty_args *) ptrarg;
294 SERIAL_SET_TTY_STATE (args->serial, args->state);
295 free (args->state);
cac390d4
SG
296 warning ("\n\nYou may need to reset the 80960 and/or reload your program.\n");
297}
298
299/* Recover from ^Z or ^C while remote process is running */
300static void (*old_ctrlc)();
301#ifdef SIGTSTP
302static void (*old_ctrlz)();
303#endif
304
305static void
306clean_up_int()
307{
308 SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
309 free (tty_args.state);
310
311 signal(SIGINT, old_ctrlc);
312#ifdef SIGTSTP
313 signal(SIGTSTP, old_ctrlz);
314#endif
315 error("\n\nYou may need to reset the 80960 and/or reload your program.\n");
704deef2 316}
dd3b648e
RP
317
318/* Wait until the remote machine stops. While waiting, operate in passthrough
199b2450 319 * mode; i.e., pass everything NINDY sends to gdb_stdout, and everything from
dd3b648e
RP
320 * stdin to NINDY.
321 *
322 * Return to caller, storing status in 'status' just as `wait' would.
323 */
324
e4db3f3e 325static int
de43d7d0
SG
326nindy_wait( pid, status )
327 int pid;
67ac9759 328 struct target_waitstatus *status;
dd3b648e 329{
704deef2 330 fd_set fds;
cac390d4
SG
331 int c;
332 char buf[2];
704deef2
JK
333 int i, n;
334 unsigned char stop_exit;
335 unsigned char stop_code;
704deef2
JK
336 struct cleanup *old_cleanups;
337 long ip_value, fp_value, sp_value; /* Reg values from stop */
338
67ac9759
JK
339 status->kind = TARGET_WAITKIND_EXITED;
340 status->value.integer = 0;
704deef2
JK
341
342 /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
343
344 /* Save current tty attributes, and restore them when done. */
345 tty_args.serial = SERIAL_FDOPEN (0);
346 tty_args.state = SERIAL_GET_TTY_STATE (tty_args.serial);
cac390d4
SG
347 old_ctrlc = signal( SIGINT, clean_up_int );
348#ifdef SIGTSTP
349 old_ctrlz = signal( SIGTSTP, clean_up_int );
350#endif
351
704deef2
JK
352 old_cleanups = make_cleanup (clean_up_tty, &tty_args);
353
354 /* Pass input from keyboard to NINDY as it arrives. NINDY will interpret
355 <CR> and perform echo. */
356 /* This used to set CBREAK and clear ECHO and CRMOD. I hope this is close
357 enough. */
358 SERIAL_RAW (tty_args.serial);
359
360 while (1)
361 {
9b73a467
KH
362 /* Input on remote */
363 c = SERIAL_READCHAR (nindy_serial, -1);
364 if (c == SERIAL_ERROR)
365 {
366 error ("Cannot read from serial line");
367 }
368 else if (c == 0x1b) /* ESC */
369 {
89fd75ae 370 c = SERIAL_READCHAR (nindy_serial, -1);
9b73a467
KH
371 c &= ~0x40;
372 }
373 else if (c != 0x10) /* DLE */
374 /* Write out any characters preceding DLE */
375 {
376 buf[0] = (char)c;
377 write (1, buf, 1);
378 }
379 else
380 {
381 stop_exit = ninStopWhy(&stop_code,
382 &ip_value, &fp_value, &sp_value);
383 if (!stop_exit && (stop_code == STOP_SRQ))
cac390d4 384 {
9b73a467
KH
385 immediate_quit++;
386 ninSrq();
387 immediate_quit--;
cac390d4
SG
388 }
389 else
704deef2 390 {
9b73a467
KH
391 /* Get out of loop */
392 supply_register (IP_REGNUM,
393 (char *)&ip_value);
394 supply_register (FP_REGNUM,
395 (char *)&fp_value);
396 supply_register (SP_REGNUM,
397 (char *)&sp_value);
398 break;
704deef2 399 }
9b73a467 400 }
704deef2 401 }
dd3b648e 402
cac390d4
SG
403 SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
404 free (tty_args.state);
405 discard_cleanups (old_cleanups);
704deef2
JK
406
407 if (stop_exit)
408 {
67ac9759
JK
409 status->kind = TARGET_WAITKIND_EXITED;
410 status->value.integer = stop_code;
704deef2
JK
411 }
412 else
413 {
cac390d4
SG
414 /* nindy has some special stop code need to be handled */
415 if (stop_code == STOP_GDB_BPT)
416 stop_code = TRACE_STEP;
67ac9759
JK
417 status->kind = TARGET_WAITKIND_STOPPED;
418 status->value.sig = i960_fault_to_signal (stop_code);
704deef2
JK
419 }
420 return inferior_pid;
dd3b648e
RP
421}
422
423/* Read the remote registers into the block REGS. */
424
425/* This is the block that ninRegsGet and ninRegsPut handles. */
426struct nindy_regs {
427 char local_regs[16 * 4];
428 char global_regs[16 * 4];
429 char pcw_acw[2 * 4];
430 char ip[4];
431 char tcw[4];
432 char fp_as_double[4 * 8];
433};
434
120f867e 435static void
dd3b648e
RP
436nindy_fetch_registers(regno)
437 int regno;
438{
439 struct nindy_regs nindy_regs;
440 int regnum, inv;
441 double dub;
442
443 immediate_quit++;
444 ninRegsGet( (char *) &nindy_regs );
445 immediate_quit--;
446
704deef2
JK
447 memcpy (&registers[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16*4);
448 memcpy (&registers[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4);
449 memcpy (&registers[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2*4);
450 memcpy (&registers[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1*4);
451 memcpy (&registers[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 1*4);
dd3b648e
RP
452 for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
453 dub = unpack_double (builtin_type_double,
454 &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
455 &inv);
456 /* dub now in host byte order */
48792545 457 floatformat_from_double (&floatformat_i960_ext, &dub,
dd3b648e
RP
458 &registers[REGISTER_BYTE (regnum)]);
459 }
460
461 registers_fetched ();
dd3b648e
RP
462}
463
464static void
465nindy_prepare_to_store()
466{
4ddd278f
JG
467 /* Fetch all regs if they aren't already here. */
468 read_register_bytes (0, NULL, REGISTER_BYTES);
dd3b648e
RP
469}
470
120f867e 471static void
dd3b648e
RP
472nindy_store_registers(regno)
473 int regno;
474{
475 struct nindy_regs nindy_regs;
bf5c0d64 476 int regnum;
dd3b648e
RP
477 double dub;
478
704deef2
JK
479 memcpy (nindy_regs.local_regs, &registers[REGISTER_BYTE (R0_REGNUM)], 16*4);
480 memcpy (nindy_regs.global_regs, &registers[REGISTER_BYTE (G0_REGNUM)], 16*4);
481 memcpy (nindy_regs.pcw_acw, &registers[REGISTER_BYTE (PCW_REGNUM)], 2*4);
482 memcpy (nindy_regs.ip, &registers[REGISTER_BYTE (IP_REGNUM)], 1*4);
483 memcpy (nindy_regs.tcw, &registers[REGISTER_BYTE (TCW_REGNUM)], 1*4);
bf5c0d64
JK
484 for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++)
485 {
48792545
JK
486 floatformat_to_double (&floatformat_i960_ext,
487 &registers[REGISTER_BYTE (regnum)], &dub);
bf5c0d64
JK
488 store_floating (&nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
489 REGISTER_VIRTUAL_SIZE (regnum),
490 dub);
491 }
dd3b648e
RP
492
493 immediate_quit++;
494 ninRegsPut( (char *) &nindy_regs );
495 immediate_quit--;
dd3b648e
RP
496}
497
498/* Read a word from remote address ADDR and return it.
499 * This goes through the data cache.
500 */
501int
502nindy_fetch_word (addr)
503 CORE_ADDR addr;
504{
5a0a463f 505 return dcache_fetch (nindy_dcache, addr);
dd3b648e
RP
506}
507
508/* Write a word WORD into remote address ADDR.
509 This goes through the data cache. */
510
511void
512nindy_store_word (addr, word)
513 CORE_ADDR addr;
514 int word;
515{
5a0a463f 516 dcache_poke (nindy_dcache, addr, word);
dd3b648e
RP
517}
518
519/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
520 to debugger memory starting at MYADDR. Copy to inferior if
521 WRITE is nonzero. Returns the length copied.
522
523 This is stolen almost directly from infptrace.c's child_xfer_memory,
524 which also deals with a word-oriented memory interface. Sometime,
525 FIXME, rewrite this to not use the word-oriented routines. */
526
527int
8f1f2a72 528nindy_xfer_inferior_memory(memaddr, myaddr, len, write, target)
dd3b648e
RP
529 CORE_ADDR memaddr;
530 char *myaddr;
531 int len;
532 int write;
8f1f2a72 533 struct target_ops *target; /* ignored */
dd3b648e
RP
534{
535 register int i;
536 /* Round starting address down to longword boundary. */
537 register CORE_ADDR addr = memaddr & - sizeof (int);
538 /* Round ending address up; get number of longwords that makes. */
539 register int count
540 = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
541 /* Allocate buffer of that many longwords. */
542 register int *buffer = (int *) alloca (count * sizeof (int));
543
544 if (write)
545 {
546 /* Fill start and end extra bytes of buffer with existing memory data. */
547
548 if (addr != memaddr || len < (int)sizeof (int)) {
549 /* Need part of initial word -- fetch it. */
550 buffer[0] = nindy_fetch_word (addr);
551 }
552
553 if (count > 1) /* FIXME, avoid if even boundary */
554 {
555 buffer[count - 1]
556 = nindy_fetch_word (addr + (count - 1) * sizeof (int));
557 }
558
559 /* Copy data to be written over corresponding part of buffer */
560
704deef2 561 memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
dd3b648e
RP
562
563 /* Write the entire buffer. */
564
565 for (i = 0; i < count; i++, addr += sizeof (int))
566 {
567 errno = 0;
568 nindy_store_word (addr, buffer[i]);
569 if (errno)
570 return 0;
571 }
572 }
573 else
574 {
575 /* Read all the longwords */
576 for (i = 0; i < count; i++, addr += sizeof (int))
577 {
578 errno = 0;
579 buffer[i] = nindy_fetch_word (addr);
580 if (errno)
581 return 0;
582 QUIT;
583 }
584
585 /* Copy appropriate bytes out of the buffer. */
704deef2 586 memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
dd3b648e
RP
587 }
588 return len;
589}
590\f
dd3b648e
RP
591static void
592nindy_create_inferior (execfile, args, env)
593 char *execfile;
594 char *args;
595 char **env;
596{
597 int entry_pt;
598 int pid;
599
600 if (args && *args)
601 error ("Can't pass arguments to remote NINDY process");
602
603 if (execfile == 0 || exec_bfd == 0)
604 error ("No exec file specified");
605
606 entry_pt = (int) bfd_get_start_address (exec_bfd);
607
608 pid = 42;
609
5d76c8e6
JK
610 /* The "process" (board) is already stopped awaiting our commands, and
611 the program is already downloaded. We just set its PC and go. */
dd3b648e
RP
612
613 inferior_pid = pid; /* Needed for wait_for_inferior below */
614
615 clear_proceed_status ();
616
dd3b648e
RP
617 /* Tell wait_for_inferior that we've started a new process. */
618 init_wait_for_inferior ();
619
620 /* Set up the "saved terminal modes" of the inferior
621 based on what modes we are starting it with. */
622 target_terminal_init ();
623
624 /* Install inferior's terminal modes. */
625 target_terminal_inferior ();
626
dd3b648e 627 /* insert_step_breakpoint (); FIXME, do we need this? */
45dc9be3
JK
628 /* Let 'er rip... */
629 proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
dd3b648e
RP
630}
631
632static void
633reset_command(args, from_tty)
634 char *args;
635 int from_tty;
636{
704deef2
JK
637 if (nindy_serial == NULL)
638 {
639 error( "No target system to reset -- use 'target nindy' command.");
640 }
641 if ( query("Really reset the target system?",0,0) )
642 {
643 SERIAL_SEND_BREAK (nindy_serial);
644 tty_flush (nindy_serial);
645 }
dd3b648e
RP
646}
647
648void
649nindy_kill (args, from_tty)
650 char *args;
651 int from_tty;
652{
653 return; /* Ignore attempts to kill target system */
654}
655
656/* Clean up when a program exits.
657
658 The program actually lives on in the remote processor's RAM, and may be
659 run again without a download. Don't leave it full of breakpoint
660 instructions. */
661
662void
663nindy_mourn_inferior ()
664{
665 remove_breakpoints ();
71607f9d 666 unpush_target (&nindy_ops);
dd3b648e
RP
667 generic_mourn_inferior (); /* Do all the proper things now */
668}
669\f
9748446f
JK
670/* Pass the args the way catch_errors wants them. */
671static int
672nindy_open_stub (arg)
673 char *arg;
674{
675 nindy_open (arg, 1);
676 return 1;
677}
678
8a7143f4
KH
679static void
680nindy_load( filename, from_tty )
681 char *filename;
682 int from_tty;
683{
684 asection *s;
685 /* Can't do unix style forking on a VMS system, so we'll use bfd to do
686 all the work for us
687 */
688
689 bfd *file = bfd_openr(filename,0);
690 if (!file)
691 {
692 perror_with_name(filename);
693 return;
694 }
695
696 if (!bfd_check_format(file, bfd_object))
697 {
698 error("can't prove it's an object file\n");
699 return;
700 }
701
702 for ( s = file->sections; s; s=s->next)
703 {
704 if (s->flags & SEC_LOAD)
705 {
706 char *buffer = xmalloc(s->_raw_size);
707 bfd_get_section_contents(file, s, buffer, 0, s->_raw_size);
708 printf("Loading section %s, size %x vma %x\n",
709 s->name,
710 s->_raw_size,
711 s->vma);
712 ninMemPut(s->vma, buffer, s->_raw_size);
713 free(buffer);
714 }
715 }
716 bfd_close(file);
717}
718
9748446f
JK
719static int
720load_stub (arg)
721 char *arg;
722{
723 target_load (arg, 1);
724 return 1;
725}
726
dd3b648e
RP
727/* This routine is run as a hook, just before the main command loop is
728 entered. If gdb is configured for the i960, but has not had its
729 nindy target specified yet, this will loop prompting the user to do so.
730
731 Unlike the loop provided by Intel, we actually let the user get out
732 of this with a RETURN. This is useful when e.g. simply examining
733 an i960 object file on the host system. */
734
df86eb44 735void
dd3b648e
RP
736nindy_before_main_loop ()
737{
738 char ttyname[100];
739 char *p, *p2;
740
cad1498f
SG
741 while (target_stack->target_ops != &nindy_ops) /* What is this crap??? */
742 { /* remote tty not specified yet */
dd3b648e 743 if ( instream == stdin ){
199b2450
TL
744 printf_unfiltered("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit: ");
745 gdb_flush( gdb_stdout );
dd3b648e
RP
746 }
747 fgets( ttyname, sizeof(ttyname)-1, stdin );
748
749 /* Strip leading and trailing whitespace */
750 for ( p = ttyname; isspace(*p); p++ ){
751 ;
752 }
753 if ( *p == '\0' ){
754 return; /* User just hit spaces or return, wants out */
755 }
756 for ( p2= p; !isspace(*p2) && (*p2 != '\0'); p2++ ){
757 ;
758 }
759 *p2= '\0';
2e4964ad 760 if ( STREQ("quit",p) ){
dd3b648e
RP
761 exit(1);
762 }
763
9748446f
JK
764 if (catch_errors (nindy_open_stub, p, "", RETURN_MASK_ALL))
765 {
766 /* Now that we have a tty open for talking to the remote machine,
767 download the executable file if one was specified. */
768 if (exec_bfd)
769 {
770 catch_errors (load_stub, bfd_get_filename (exec_bfd), "",
771 RETURN_MASK_ALL);
772 }
773 }
9b73a467 774 }
dd3b648e
RP
775}
776\f
777/* Define the target subroutine names */
778
779struct target_ops nindy_ops = {
780 "nindy", "Remote serial target in i960 NINDY-specific protocol",
f2fc6e7a
JK
781 "Use a remote i960 system running NINDY connected by a serial line.\n\
782Specify the name of the device the serial line is connected to.\n\
783The speed (baud rate), whether to use the old NINDY protocol,\n\
784and whether to send a break on startup, are controlled by options\n\
785specified when you started GDB.",
dd3b648e 786 nindy_open, nindy_close,
58bcc08c
JG
787 0,
788 nindy_detach,
789 nindy_resume,
790 nindy_wait,
dd3b648e 791 nindy_fetch_registers, nindy_store_registers,
a03d4f8e 792 nindy_prepare_to_store,
dd3b648e 793 nindy_xfer_inferior_memory, nindy_files_info,
771d7a99
SC
794 memory_insert_breakpoint,
795 memory_remove_breakpoint,
dd3b648e
RP
796 0, 0, 0, 0, 0, /* Terminal crud */
797 nindy_kill,
8a7143f4 798 nindy_load,
dd3b648e
RP
799 0, /* lookup_symbol */
800 nindy_create_inferior,
801 nindy_mourn_inferior,
0256270d
KR
802 0, /* can_run */
803 0, /* notice_signals */
78b459a7 804 0, /* to_stop */
dd3b648e
RP
805 process_stratum, 0, /* next */
806 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
8f1f2a72 807 0, 0, /* Section pointers */
dd3b648e
RP
808 OPS_MAGIC, /* Always the last thing */
809};
810
811void
812_initialize_nindy ()
813{
814 add_target (&nindy_ops);
815 add_com ("reset", class_obscure, reset_command,
816 "Send a 'break' to the remote target system.\n\
817Only useful if the target has been equipped with a circuit\n\
818to perform a hard reset when a break is detected.");
819}
This page took 0.261574 seconds and 4 git commands to generate.