]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/remote-os9k.c
* utils.c (fprintf_filtered, fprintf_unfiltered, fprintfi_filtered,
[thirdparty/binutils-gdb.git] / gdb / remote-os9k.c
CommitLineData
d5336fc5 1/* Remote debugging interface for boot monitors, for GDB.
1340861c
KH
2 Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/* This file was derived from remote-eb.c, which did a similar job, but for
21 an AMD-29K running EBMON. That file was in turn derived from remote.c
22 as mentioned in the following comment (left in for comic relief):
23
24 "This is like remote.c but is for a different situation--
25 having a PC running os9000 hook up with a unix machine with
26 a serial line, and running ctty com2 on the PC. os9000 has a debug
27 monitor called ROMBUG running. Not to mention that the PC
28 has PC/NFS, so it can access the same executables that gdb can,
29 over the net in real time."
30
31 In reality, this module talks to a debug monitor called 'ROMBUG', which
32 We communicate with ROMBUG via a direct serial line, the network version
33 of ROMBUG is not available yet.
34*/
35
36#include "defs.h"
37#include "gdbcore.h"
38#include "target.h"
39#include "wait.h"
85c613aa
C
40#ifdef __STDC__
41#include <stdarg.h>
42#else
1340861c 43#include <varargs.h>
85c613aa 44#endif
1340861c
KH
45#include <signal.h>
46#include <string.h>
47#include <sys/types.h>
48#include "command.h"
49#include "serial.h"
50#include "monitor.h"
51#include "remote-utils.h"
52#include "symtab.h"
53#include "symfile.h"
54#include "objfiles.h"
55#include "gdb-stabs.h"
1340861c
KH
56
57struct monitor_ops *current_monitor;
58struct cmd_list_element *showlist;
59extern struct target_ops rombug_ops; /* Forward declaration */
60extern struct monitor_ops rombug_cmds; /* Forward declaration */
61extern struct cmd_list_element *setlist;
62extern struct cmd_list_element *unsetlist;
63extern int attach_flag;
64
65static void rombug_close();
66static void rombug_fetch_register();
67static void rombug_fetch_registers();
68static void rombug_store_register();
69#if 0
70static int sr_get_debug(); /* flag set by "set remotedebug" */
71#endif
72static int hashmark; /* flag set by "set hash" */
73static int rombug_is_open = 0;
74
75/* FIXME: Replace with sr_get_debug (). */
76#define LOG_FILE "monitor.log"
1340861c 77FILE *log_file;
d9389f37 78static int monitor_log = 0;
d80ff70c
KH
79static int tty_xon = 0;
80static int tty_xoff = 0;
1340861c 81
d5336fc5 82static int timeout = 10;
1340861c
KH
83static int is_trace_mode = 0;
84/* Descriptor for I/O to remote machine. Initialize it to NULL*/
85static serial_t monitor_desc = NULL;
86
d5336fc5
KH
87static CORE_ADDR bufaddr = 0;
88static int buflen = 0;
89static char readbuf[16];
90
1340861c
KH
91/* Send data to monitor. Works just like printf. */
92static void
85c613aa
C
93#ifdef __STDC__
94printf_monitor(char *pattern, ...)
95#else
1340861c
KH
96printf_monitor(va_alist)
97 va_dcl
85c613aa 98#endif
1340861c
KH
99{
100 va_list args;
1340861c
KH
101 char buf[200];
102 int i;
103
85c613aa
C
104#ifdef __STDC__
105 va_start (args, pattern);
106#else
107 char *pattern;
1340861c 108 va_start(args);
1340861c 109 pattern = va_arg(args, char *);
85c613aa 110#endif
1340861c
KH
111
112 vsprintf(buf, pattern, args);
85c613aa 113 va_end(args);
1340861c
KH
114
115 if (SERIAL_WRITE(monitor_desc, buf, strlen(buf)))
116 fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
117}
118
119/* Read a character from the remote system, doing all the fancy timeout stuff*/
120static int
121readchar(timeout)
122 int timeout;
123{
124 int c;
125
126 c = SERIAL_READCHAR(monitor_desc, timeout);
127
128 if (sr_get_debug())
129 putchar(c & 0x7f);
130
d9389f37 131 if (monitor_log && isascii(c))
1340861c 132 putc(c & 0x7f, log_file);
1340861c
KH
133
134 if (c >= 0)
135 return c & 0x7f;
136
137 if (c == SERIAL_TIMEOUT)
138 {
139 if (timeout == 0)
140 return c; /* Polls shouldn't generate timeout errors */
141
142 error("Timeout reading from remote system.");
143 }
144
145 perror_with_name("remote-monitor");
146}
147
148/* Scan input from the remote system, until STRING is found. If DISCARD is
149 non-zero, then discard non-matching input, else print it out.
150 Let the user break out immediately. */
151static void
152expect(string, discard)
153 char *string;
154 int discard;
155{
156 char *p = string;
157 int c;
158
159 if (sr_get_debug())
160 printf ("Expecting \"%s\"\n", string);
161
162 immediate_quit = 1;
163 while (1)
164 {
165 c = readchar(timeout);
166 if (!isascii (c))
167 continue;
168 if (c == *p++)
169 {
170 if (*p == '\0')
171 {
172 immediate_quit = 0;
173 if (sr_get_debug())
174 printf ("\nMatched\n");
175 return;
176 }
177 }
178 else
179 {
180 if (!discard)
181 {
182 fwrite(string, 1, (p - 1) - string, stdout);
183 putchar((char)c);
184 fflush(stdout);
185 }
186 p = string;
187 }
188 }
189}
190
191/* Keep discarding input until we see the ROMBUG prompt.
192
193 The convention for dealing with the prompt is that you
194 o give your command
195 o *then* wait for the prompt.
196
197 Thus the last thing that a procedure does with the serial line
198 will be an expect_prompt(). Exception: rombug_resume does not
199 wait for the prompt, because the terminal is being handed over
200 to the inferior. However, the next thing which happens after that
201 is a rombug_wait which does wait for the prompt.
202 Note that this includes abnormal exit, e.g. error(). This is
203 necessary to prevent getting into states from which we can't
204 recover. */
205static void
206expect_prompt(discard)
207 int discard;
208{
d9389f37 209 if (monitor_log)
1340861c
KH
210 /* This is a convenient place to do this. The idea is to do it often
211 enough that we never lose much data if we terminate abnormally. */
d9389f37
KH
212 fflush(log_file);
213
1340861c
KH
214 if (is_trace_mode) {
215 expect("trace", discard);
1340861c
KH
216 } else {
217 expect (PROMPT, discard);
218 }
219}
220
221/* Get a hex digit from the remote system & return its value.
222 If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
223static int
224get_hex_digit(ignore_space)
225 int ignore_space;
226{
227 int ch;
228 while (1)
229 {
230 ch = readchar(timeout);
231 if (ch >= '0' && ch <= '9')
232 return ch - '0';
233 else if (ch >= 'A' && ch <= 'F')
234 return ch - 'A' + 10;
235 else if (ch >= 'a' && ch <= 'f')
236 return ch - 'a' + 10;
237 else if (ch == ' ' && ignore_space)
238 ;
239 else
240 {
241 expect_prompt(1);
242 error("Invalid hex digit from remote system.");
243 }
244 }
245}
246
247/* Get a byte from monitor and put it in *BYT. Accept any number
248 leading spaces. */
249static void
250get_hex_byte (byt)
251 char *byt;
252{
253 int val;
254
255 val = get_hex_digit (1) << 4;
256 val |= get_hex_digit (0);
257 *byt = val;
258}
259
260/* Get N 32-bit words from remote, each preceded by a space,
261 and put them in registers starting at REGNO. */
262static void
263get_hex_regs (n, regno)
264 int n;
265 int regno;
266{
267 long val;
268 int i;
269 unsigned char b;
270
271 for (i = 0; i < n; i++)
272 {
273 int j;
274
275 val = 0;
276 for (j = 0; j < 4; j++)
277 {
b8176214
ILT
278 get_hex_byte (&b);
279 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
280 val = (val << 8) + b;
281 else
282 val = val + (b << (j*8));
1340861c
KH
283 }
284 supply_register (regno++, (char *) &val);
285 }
286}
287
288/* This is called not only when we first attach, but also when the
289 user types "run" after having attached. */
290static void
291rombug_create_inferior (execfile, args, env)
292 char *execfile;
293 char *args;
294 char **env;
295{
296 int entry_pt;
297
298 if (args && *args)
299 error("Can't pass arguments to remote ROMBUG process");
300
301 if (execfile == 0 || exec_bfd == 0)
302 error("No exec file specified");
303
304 entry_pt = (int) bfd_get_start_address (exec_bfd);
305
d9389f37
KH
306 if (monitor_log)
307 fputs ("\nIn Create_inferior()", log_file);
308
1340861c
KH
309
310/* The "process" (board) is already stopped awaiting our commands, and
311 the program is already downloaded. We just set its PC and go. */
312
313 init_wait_for_inferior ();
314 proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
315}
316
317/* Open a connection to a remote debugger.
318 NAME is the filename used for communication. */
319
1340861c
KH
320static char dev_name[100];
321
322static void
323rombug_open(args, from_tty)
324 char *args;
325 int from_tty;
326{
327 if (args == NULL)
328 error ("Use `target RomBug DEVICE-NAME' to use a serial port, or \n\
329`target RomBug HOST-NAME:PORT-NUMBER' to use a network connection.");
330
331 target_preopen(from_tty);
332
333 if (rombug_is_open)
334 unpush_target(&rombug_ops);
335
336 strcpy(dev_name, args);
337 monitor_desc = SERIAL_OPEN(dev_name);
338 if (monitor_desc == NULL)
339 perror_with_name(dev_name);
340
d9389f37 341 /* if baud rate is set by 'set remotebaud' */
1340861c
KH
342 if (SERIAL_SETBAUDRATE (monitor_desc, sr_get_baud_rate()))
343 {
344 SERIAL_CLOSE (monitor_desc);
345 perror_with_name ("RomBug");
346 }
1340861c 347 SERIAL_RAW(monitor_desc);
d80ff70c
KH
348 if (tty_xon || tty_xoff)
349 {
350 struct hardware_ttystate { struct termios t;} *tty_s;
351
352 tty_s =(struct hardware_ttystate *)SERIAL_GET_TTY_STATE(monitor_desc);
353 if (tty_xon) tty_s->t.c_iflag |= IXON;
354 if (tty_xoff) tty_s->t.c_iflag |= IXOFF;
355 SERIAL_SET_TTY_STATE(monitor_desc, (serial_ttystate) tty_s);
356 }
d9389f37 357
1340861c
KH
358 rombug_is_open = 1;
359
1340861c
KH
360 log_file = fopen (LOG_FILE, "w");
361 if (log_file == NULL)
362 perror_with_name (LOG_FILE);
1340861c
KH
363
364 push_monitor (&rombug_cmds);
1340861c
KH
365 printf_monitor("\r"); /* CR wakes up monitor */
366 expect_prompt(1);
1340861c 367 push_target (&rombug_ops);
034022bf
KH
368 attach_flag = 1;
369
1340861c
KH
370 if (from_tty)
371 printf("Remote %s connected to %s\n", target_shortname,
372 dev_name);
373
6bbc99e3
KH
374 rombug_fetch_registers();
375
034022bf
KH
376 printf_monitor ("ov e \r");
377 expect_prompt(1);
d5336fc5
KH
378 bufaddr = 0;
379 buflen = 0;
1340861c
KH
380}
381
382/*
383 * Close out all files and local state before this target loses control.
384 */
385
386static void
387rombug_close (quitting)
388 int quitting;
389{
390 if (rombug_is_open) {
391 SERIAL_CLOSE(monitor_desc);
392 monitor_desc = NULL;
393 rombug_is_open = 0;
394 }
395
1340861c
KH
396 if (log_file) {
397 if (ferror(log_file))
398 fprintf(stderr, "Error writing log file.\n");
399 if (fclose(log_file) != 0)
400 fprintf(stderr, "Error closing log file.\n");
401 log_file = 0;
402 }
1340861c
KH
403}
404
405int
406rombug_link(mod_name, text_reloc)
407 char *mod_name;
408 CORE_ADDR *text_reloc;
409{
410 int i, j;
411 unsigned long val;
412 unsigned char b;
413
414 printf_monitor("l %s \r", mod_name);
415 expect_prompt(1);
416 printf_monitor(".r \r");
417 expect(REG_DELIM, 1);
418 for (i=0; i <= 7; i++)
419 {
420 val = 0;
421 for (j = 0; j < 4; j++)
422 {
423 get_hex_byte(&b);
424 val = (val << 8) + b;
425 }
426 }
427 expect_prompt(1);
428 *text_reloc = val;
429 return 1;
430}
431
432/* Terminate the open connection to the remote debugger.
433 Use this when you want to detach and do something else
434 with your gdb. */
435static void
436rombug_detach (from_tty)
437 int from_tty;
438{
439 if (attach_flag) {
440 printf_monitor (GO_CMD);
441 attach_flag = 0;
442 }
443 pop_target(); /* calls rombug_close to do the real work */
444 if (from_tty)
445 printf ("Ending remote %s debugging\n", target_shortname);
446}
447
448/*
449 * Tell the remote machine to resume.
450 */
451static void
452rombug_resume (pid, step, sig)
453 int pid, step;
454 enum target_signal sig;
455{
d9389f37
KH
456 if (monitor_log)
457 fprintf (log_file, "\nIn Resume (step=%d, sig=%d)\n", step, sig);
1340861c
KH
458
459 if (step)
460 {
461 is_trace_mode = 1;
462 printf_monitor (STEP_CMD);
d5336fc5 463 /* wait for the echo. **
1340861c 464 expect (STEP_CMD, 1);
d5336fc5 465 */
1340861c
KH
466 }
467 else
468 {
469 printf_monitor (GO_CMD);
d5336fc5 470 /* swallow the echo. **
1340861c 471 expect (GO_CMD, 1);
d5336fc5 472 */
1340861c 473 }
d5336fc5
KH
474 bufaddr = 0;
475 buflen= 0;
1340861c
KH
476}
477
478/*
479 * Wait until the remote machine stops, then return,
480 * storing status in status just as `wait' would.
481 */
482
483static int
484rombug_wait (pid, status)
485 int pid;
486 struct target_waitstatus *status;
487{
488 int old_timeout = timeout;
489 struct section_offsets *offs;
490 CORE_ADDR addr, pc;
25200748 491 struct obj_section *obj_sec;
1340861c 492
d9389f37
KH
493 if (monitor_log)
494 fputs ("\nIn wait ()", log_file);
1340861c
KH
495
496 status->kind = TARGET_WAITKIND_EXITED;
497 status->value.integer = 0;
498
034022bf
KH
499 timeout = -1; /* Don't time out -- user program is running. */
500 expect ("eax:", 0); /* output any message before register display */
1340861c
KH
501 expect_prompt(1); /* Wait for prompt, outputting extraneous text */
502
503 status->kind = TARGET_WAITKIND_STOPPED;
504 status->value.sig = TARGET_SIGNAL_TRAP;
505 timeout = old_timeout;
506 rombug_fetch_registers();
d5336fc5
KH
507 bufaddr = 0;
508 buflen = 0;
1340861c
KH
509 pc = read_register(PC_REGNUM);
510 addr = read_register(DATABASE_REG);
25200748
JK
511 obj_sec = find_pc_section (pc);
512 if (obj_sec != NULL)
d9389f37
KH
513 {
514 if (obj_sec->objfile != symfile_objfile)
515 new_symfile_objfile(obj_sec->objfile, 1, 0);
516 offs = ((struct section_offsets *)
1340861c
KH
517 alloca (sizeof (struct section_offsets)
518 + (symfile_objfile->num_sections * sizeof (offs->offsets))));
d9389f37 519 memcpy (offs, symfile_objfile->section_offsets,
1340861c
KH
520 (sizeof (struct section_offsets) +
521 (symfile_objfile->num_sections * sizeof (offs->offsets))));
d9389f37
KH
522 ANOFFSET (offs, SECT_OFF_DATA) = addr;
523 ANOFFSET (offs, SECT_OFF_BSS) = addr;
1340861c 524
d9389f37
KH
525 objfile_relocate(symfile_objfile, offs);
526 }
d5336fc5 527
1340861c
KH
528 return 0;
529}
530
531/* Return the name of register number regno in the form input and output by
532 monitor. Currently, register_names just happens to contain exactly what
533 monitor wants. Lets take advantage of that just as long as possible! */
534
535static char *
536get_reg_name (regno)
537 int regno;
538{
539 static char buf[50];
540 char *p;
541 char *b;
542
543 b = buf;
544
545 if (regno < 0)
546 return ("");
547/*
548 for (p = reg_names[regno]; *p; p++)
549 *b++ = toupper(*p);
550 *b = '\000';
551*/
552 p = (char *)reg_names[regno];
553 return p;
554/*
555 return buf;
556*/
557}
558
559/* read the remote registers into the block regs. */
560
561static void
562rombug_fetch_registers ()
563{
564 int regno, j, i;
565 long val;
566 unsigned char b;
567
568 printf_monitor (GET_REG);
569 expect("eax:", 1);
570 expect("\n", 1);
571 get_hex_regs(1, 0);
572 get_hex_regs(1, 3);
573 get_hex_regs(1, 1);
574 get_hex_regs(1, 2);
575 get_hex_regs(1, 6);
576 get_hex_regs(1, 7);
577 get_hex_regs(1, 5);
578 get_hex_regs(1, 4);
579 for (regno = 8; regno <= 15; regno++)
580 {
581 expect(REG_DELIM, 1);
582 if (regno >= 8 && regno <= 13)
583 {
584 val = 0;
585 for (j = 0; j < 2; j++)
586 {
b8176214
ILT
587 get_hex_byte (&b);
588 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
589 val = (val << 8) + b;
590 else
591 val = val + (b << (j*8));
1340861c
KH
592 }
593
594 if (regno == 8) i = 10;
595 if (regno >= 9 && regno <= 12) i = regno + 3;
596 if (regno == 13) i = 11;
597 supply_register (i, (char *) &val);
598 }
599 else if (regno == 14)
600 {
601 get_hex_regs(1, PC_REGNUM);
602 }
603 else if (regno == 15)
604 {
605 get_hex_regs(1, 9);
606 }
607 else
608 {
609 val = 0;
610 supply_register(regno, (char *) &val);
611 }
612 }
d5336fc5 613 is_trace_mode = 0;
1340861c
KH
614 expect_prompt (1);
615}
616
617/* Fetch register REGNO, or all registers if REGNO is -1.
618 Returns errno value. */
619static void
620rombug_fetch_register (regno)
621 int regno;
622{
623 int val, j;
624 unsigned char b;
625
d9389f37
KH
626 if (monitor_log) {
627 fprintf (log_file, "\nIn Fetch Register (reg=%s)\n", get_reg_name (regno));
628 fflush (log_file);
629 }
1340861c
KH
630
631 if (regno < 0)
632 {
633 rombug_fetch_registers ();
634 }
635 else
636 {
637 char *name = get_reg_name (regno);
638 printf_monitor (GET_REG);
639 if (regno >= 10 && regno <= 15)
640 {
641 expect ("\n", 1);
642 expect ("\n", 1);
643 expect (name, 1);
644 expect (REG_DELIM, 1);
645 val = 0;
646 for (j = 0; j < 2; j++)
647 {
b8176214
ILT
648 get_hex_byte (&b);
649 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
650 val = (val << 8) + b;
651 else
652 val = val + (b << (j*8));
1340861c
KH
653 }
654 supply_register (regno, (char *) &val);
655 }
656 else if (regno == 8 || regno == 9)
657 {
658 expect ("\n", 1);
659 expect ("\n", 1);
660 expect ("\n", 1);
661 expect (name, 1);
662 expect (REG_DELIM, 1);
663 get_hex_regs (1, regno);
664 }
665 else
666 {
667 expect (name, 1);
668 expect (REG_DELIM, 1);
669 expect("\n", 1);
670 get_hex_regs(1, 0);
671 get_hex_regs(1, 3);
672 get_hex_regs(1, 1);
673 get_hex_regs(1, 2);
674 get_hex_regs(1, 6);
675 get_hex_regs(1, 7);
676 get_hex_regs(1, 5);
677 get_hex_regs(1, 4);
678 }
679 expect_prompt (1);
680 }
681 return;
682}
683
684/* Store the remote registers from the contents of the block REGS. */
685
686static void
687rombug_store_registers ()
688{
689 int regno;
690
691 for (regno = 0; regno <= PC_REGNUM; regno++)
692 rombug_store_register(regno);
693
694 registers_changed ();
695}
696
697/* Store register REGNO, or all if REGNO == 0.
698 return errno value. */
699static void
700rombug_store_register (regno)
701 int regno;
702{
703char *name;
704
d9389f37
KH
705 if (monitor_log)
706 fprintf (log_file, "\nIn Store_register (regno=%d)\n", regno);
707
1340861c
KH
708 if (regno == -1)
709 rombug_store_registers ();
710 else
711 {
712 if (sr_get_debug())
713 printf ("Setting register %s to 0x%x\n", get_reg_name (regno), read_register (regno));
714
715 name = get_reg_name(regno);
716 if (name == 0) return;
717 printf_monitor (SET_REG, name, read_register (regno));
718
d5336fc5 719 is_trace_mode = 0;
1340861c
KH
720 expect_prompt (1);
721 }
722}
723
724/* Get ready to modify the registers array. On machines which store
725 individual registers, this doesn't need to do anything. On machines
726 which store all the registers in one fell swoop, this makes sure
727 that registers contains all the registers from the program being
728 debugged. */
729
730static void
731rombug_prepare_to_store ()
732{
733 /* Do nothing, since we can store individual regs */
734}
735
736static void
737rombug_files_info ()
738{
739 printf ("\tAttached to %s at %d baud.\n",
d9389f37 740 dev_name, sr_get_baud_rate());
1340861c
KH
741}
742
743/* Copy LEN bytes of data from debugger memory at MYADDR
744 to inferior's memory at MEMADDR. Returns length moved. */
745static int
746rombug_write_inferior_memory (memaddr, myaddr, len)
747 CORE_ADDR memaddr;
748 unsigned char *myaddr;
749 int len;
750{
751 int i;
752 char buf[10];
753
d9389f37
KH
754 if (monitor_log)
755 fprintf (log_file, "\nIn Write_inferior_memory (memaddr=%x, len=%d)\n", memaddr, len);
756
757 printf_monitor (MEM_SET_CMD, memaddr);
1340861c
KH
758 for (i = 0; i < len; i++)
759 {
760 expect (CMD_DELIM, 1);
d9389f37 761 printf_monitor ("%x \r", myaddr[i]);
1340861c
KH
762 if (sr_get_debug())
763 printf ("\nSet 0x%x to 0x%x\n", memaddr + i, myaddr[i]);
764 }
d9389f37 765 expect (CMD_DELIM, 1);
1340861c
KH
766 if (CMD_END)
767 printf_monitor (CMD_END);
d5336fc5 768 is_trace_mode = 0;
1340861c
KH
769 expect_prompt (1);
770
6bbc99e3
KH
771 bufaddr = 0;
772 buflen = 0;
1340861c
KH
773 return len;
774}
775
776/* Read LEN bytes from inferior memory at MEMADDR. Put the result
777 at debugger address MYADDR. Returns length moved. */
778static int
779rombug_read_inferior_memory(memaddr, myaddr, len)
780 CORE_ADDR memaddr;
781 char *myaddr;
782 int len;
783{
784 int i, j;
1340861c
KH
785
786 /* Number of bytes read so far. */
787 int count;
788
789 /* Starting address of this pass. */
790 unsigned long startaddr;
791
792 /* Number of bytes to read in this pass. */
793 int len_this_pass;
794
d9389f37
KH
795 if (monitor_log)
796 fprintf (log_file, "\nIn Read_inferior_memory (memaddr=%x, len=%d)\n", memaddr, len);
1340861c
KH
797
798 /* Note that this code works correctly if startaddr is just less
799 than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
800 thing). That is, something like
801 rombug_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
802 works--it never adds len To memaddr and gets 0. */
803 /* However, something like
804 rombug_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
805 doesn't need to work. Detect it and give up if there's an attempt
806 to do that. */
807 if (((memaddr - 1) + len) < memaddr) {
808 errno = EIO;
809 return 0;
810 }
d5336fc5
KH
811 if (bufaddr <= memaddr && (memaddr+len) <= (bufaddr+buflen))
812 {
813 memcpy(myaddr, &readbuf[memaddr-bufaddr], len);
814 return len;
815 }
1340861c
KH
816
817 startaddr = memaddr;
818 count = 0;
819 while (count < len)
820 {
821 len_this_pass = 16;
822 if ((startaddr % 16) != 0)
823 len_this_pass -= startaddr % 16;
824 if (len_this_pass > (len - count))
825 len_this_pass = (len - count);
826 if (sr_get_debug())
827 printf ("\nDisplay %d bytes at %x\n", len_this_pass, startaddr);
828
d5336fc5 829 printf_monitor (MEM_DIS_CMD, startaddr, 8);
1340861c 830 expect ("- ", 1);
d5336fc5 831 for (i = 0; i < 16; i++)
1340861c 832 {
d5336fc5 833 get_hex_byte (&readbuf[i]);
1340861c 834 }
d5336fc5
KH
835 bufaddr = startaddr;
836 buflen = 16;
837 memcpy(&myaddr[count], readbuf, len_this_pass);
838 count += len_this_pass;
839 startaddr += len_this_pass;
1340861c
KH
840 expect(CMD_DELIM, 1);
841 }
842 if (CMD_END)
843 printf_monitor (CMD_END);
d5336fc5 844 is_trace_mode = 0;
1340861c
KH
845 expect_prompt (1);
846
847 return len;
848}
849
850/* FIXME-someday! merge these two. */
851static int
852rombug_xfer_inferior_memory (memaddr, myaddr, len, write, target)
853 CORE_ADDR memaddr;
854 char *myaddr;
855 int len;
856 int write;
857 struct target_ops *target; /* ignored */
858{
859 if (write)
860 return rombug_write_inferior_memory (memaddr, myaddr, len);
861 else
862 return rombug_read_inferior_memory (memaddr, myaddr, len);
863}
864
865static void
866rombug_kill (args, from_tty)
867 char *args;
868 int from_tty;
869{
870 return; /* ignore attempts to kill target system */
871}
872
873/* Clean up when a program exits.
874 The program actually lives on in the remote processor's RAM, and may be
875 run again without a download. Don't leave it full of breakpoint
876 instructions. */
877
878static void
879rombug_mourn_inferior ()
880{
881 remove_breakpoints ();
882 generic_mourn_inferior (); /* Do all the proper things now */
883}
884
885#define MAX_MONITOR_BREAKPOINTS 16
886
887extern int memory_breakpoint_size;
888static CORE_ADDR breakaddr[MAX_MONITOR_BREAKPOINTS] = {0};
889
890static int
891rombug_insert_breakpoint (addr, shadow)
892 CORE_ADDR addr;
893 char *shadow;
894{
895 int i;
896
d9389f37
KH
897 if (monitor_log)
898 fprintf (log_file, "\nIn Insert_breakpoint (addr=%x)\n", addr);
899
1340861c
KH
900 for (i = 0; i <= MAX_MONITOR_BREAKPOINTS; i++)
901 if (breakaddr[i] == 0)
902 {
903 breakaddr[i] = addr;
904 if (sr_get_debug())
905 printf ("Breakpoint at %x\n", addr);
906 rombug_read_inferior_memory(addr, shadow, memory_breakpoint_size);
907 printf_monitor(SET_BREAK_CMD, addr);
d5336fc5 908 is_trace_mode = 0;
1340861c
KH
909 expect_prompt(1);
910 return 0;
911 }
912
913 fprintf(stderr, "Too many breakpoints (> 16) for monitor\n");
914 return 1;
915}
916
917/*
918 * _remove_breakpoint -- Tell the monitor to remove a breakpoint
919 */
920static int
921rombug_remove_breakpoint (addr, shadow)
922 CORE_ADDR addr;
923 char *shadow;
924{
925 int i;
926
d9389f37
KH
927 if (monitor_log)
928 fprintf (log_file, "\nIn Remove_breakpoint (addr=%x)\n", addr);
929
1340861c
KH
930 for (i = 0; i < MAX_MONITOR_BREAKPOINTS; i++)
931 if (breakaddr[i] == addr)
932 {
933 breakaddr[i] = 0;
d9389f37 934 printf_monitor(CLR_BREAK_CMD, addr);
d5336fc5 935 is_trace_mode = 0;
1340861c
KH
936 expect_prompt(1);
937 return 0;
938 }
939
940 fprintf(stderr, "Can't find breakpoint associated with 0x%x\n", addr);
941 return 1;
942}
943
944/* Load a file. This is usually an srecord, which is ascii. No
945 protocol, just sent line by line. */
946
947#define DOWNLOAD_LINE_SIZE 100
948static void
949rombug_load (arg)
950 char *arg;
951{
952/* this part comment out for os9* */
953#if 0
954 FILE *download;
955 char buf[DOWNLOAD_LINE_SIZE];
956 int i, bytes_read;
957
958 if (sr_get_debug())
959 printf ("Loading %s to monitor\n", arg);
960
961 download = fopen (arg, "r");
962 if (download == NULL)
963 {
964 error (sprintf (buf, "%s Does not exist", arg));
965 return;
966 }
967
968 printf_monitor (LOAD_CMD);
969/* expect ("Waiting for S-records from host... ", 1); */
970
971 while (!feof (download))
972 {
973 bytes_read = fread (buf, sizeof (char), DOWNLOAD_LINE_SIZE, download);
974 if (hashmark)
975 {
976 putchar ('.');
977 fflush (stdout);
978 }
979
980 if (SERIAL_WRITE(monitor_desc, buf, bytes_read)) {
981 fprintf(stderr, "SERIAL_WRITE failed: (while downloading) %s\n", safe_strerror(errno));
982 break;
983 }
984 i = 0;
985 while (i++ <=200000) {} ; /* Ugly HACK, probably needs flow control */
986 if (bytes_read < DOWNLOAD_LINE_SIZE)
987 {
988 if (!feof (download))
989 error ("Only read %d bytes\n", bytes_read);
990 break;
991 }
992 }
993
994 if (hashmark)
995 {
996 putchar ('\n');
997 }
998 if (!feof (download))
999 error ("Never got EOF while downloading");
1000 fclose (download);
1001#endif 0
1002}
1003
1004/* Put a command string, in args, out to MONITOR.
1005 Output from MONITOR is placed on the users terminal until the prompt
1006 is seen. */
1007
1008static void
1009rombug_command (args, fromtty)
1010 char *args;
1011 int fromtty;
1012{
1340861c
KH
1013 if (monitor_desc == NULL)
1014 error("monitor target not open.");
1015
d9389f37
KH
1016 if (monitor_log)
1017 fprintf (log_file, "\nIn command (args=%s)\n", args);
1018
1340861c
KH
1019 if (!args)
1020 error("Missing command.");
1021
1022 printf_monitor("%s\r", args);
539dccd3 1023 expect_prompt(0);
1340861c
KH
1024}
1025
1026#if 0
1027/* Connect the user directly to MONITOR. This command acts just like the
1028 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
1029
1030static struct ttystate ttystate;
1031
1032static void
1033cleanup_tty()
1034{ printf("\r\n[Exiting connect mode]\r\n");
1035 /*SERIAL_RESTORE(0, &ttystate);*/
1036}
1037
1038static void
1039connect_command (args, fromtty)
1040 char *args;
1041 int fromtty;
1042{
1043 fd_set readfds;
1044 int numfds;
1045 int c;
1046 char cur_esc = 0;
1047
1048 dont_repeat();
1049
1050 if (monitor_desc == NULL)
1051 error("monitor target not open.");
1052
1053 if (args)
1054 fprintf("This command takes no args. They have been ignored.\n");
1055
1056 printf("[Entering connect mode. Use ~. or ~^D to escape]\n");
1057
1058 serial_raw(0, &ttystate);
1059
1060 make_cleanup(cleanup_tty, 0);
1061
1062 FD_ZERO(&readfds);
1063
1064 while (1)
1065 {
1066 do
1067 {
1068 FD_SET(0, &readfds);
1069 FD_SET(monitor_desc, &readfds);
1070 numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
1071 }
1072 while (numfds == 0);
1073
1074 if (numfds < 0)
1075 perror_with_name("select");
1076
1077 if (FD_ISSET(0, &readfds))
1078 { /* tty input, send to monitor */
1079 c = getchar();
1080 if (c < 0)
1081 perror_with_name("connect");
1082
1083 printf_monitor("%c", c);
1084 switch (cur_esc)
1085 {
1086 case 0:
1087 if (c == '\r')
1088 cur_esc = c;
1089 break;
1090 case '\r':
1091 if (c == '~')
1092 cur_esc = c;
1093 else
1094 cur_esc = 0;
1095 break;
1096 case '~':
1097 if (c == '.' || c == '\004')
1098 return;
1099 else
1100 cur_esc = 0;
1101 }
1102 }
1103
1104 if (FD_ISSET(monitor_desc, &readfds))
1105 {
1106 while (1)
1107 {
1108 c = readchar(0);
1109 if (c < 0)
1110 break;
1111 putchar(c);
1112 }
1113 fflush(stdout);
1114 }
1115 }
1116}
1117#endif
1118
1119/*
1120 * Define the monitor command strings. Since these are passed directly
1121 * through to a printf style function, we need can include formatting
1122 * strings. We also need a CR or LF on the end.
1123 */
1124struct monitor_ops rombug_cmds = {
1125 "g \r", /* execute or usually GO command */
1126 "g \r", /* continue command */
d9389f37 1127 "t \r", /* single step */
1340861c
KH
1128 "b %x\r", /* set a breakpoint */
1129 "k %x\r", /* clear a breakpoint */
1130 "c %x\r", /* set memory to a value */
1131 "d %x %d\r", /* display memory */
1132 "$%08X", /* prompt memory commands use */
1133 ".%s %x\r", /* set a register */
1134 ":", /* delimiter between registers */
1135 ". \r", /* read a register */
1136 "mf \r", /* download command */
1137 "RomBug: ", /* monitor command prompt */
1138 ": ", /* end-of-command delimitor */
1139 ".\r" /* optional command terminator */
1140};
1141
1142struct target_ops rombug_ops = {
1143 "rombug",
1144 "Microware's ROMBUG debug monitor",
1145 "Use a remote computer running the ROMBUG debug monitor.\n\
1146Specify the serial device it is connected to (e.g. /dev/ttya).",
1147 rombug_open,
1148 rombug_close,
1149 0,
1150 rombug_detach,
1151 rombug_resume,
1152 rombug_wait,
1153 rombug_fetch_register,
1154 rombug_store_register,
1155 rombug_prepare_to_store,
1156 rombug_xfer_inferior_memory,
1157 rombug_files_info,
1158 rombug_insert_breakpoint,
1159 rombug_remove_breakpoint, /* Breakpoints */
1160 0,
1161 0,
1162 0,
1163 0,
1164 0, /* Terminal handling */
1165 rombug_kill,
1166 rombug_load, /* load */
d9389f37 1167 rombug_link, /* lookup_symbol */
1340861c
KH
1168 rombug_create_inferior,
1169 rombug_mourn_inferior,
1170 0, /* can_run */
1171 0, /* notice_signals */
78b459a7 1172 0, /* to_stop */
1340861c
KH
1173 process_stratum,
1174 0, /* next */
1175 1,
1176 1,
1177 1,
1178 1,
1179 1, /* has execution */
1180 0,
1181 0, /* Section pointers */
1182 OPS_MAGIC, /* Always the last thing */
1183};
1184
1185void
1186_initialize_remote_os9k ()
1187{
1188 add_target (&rombug_ops);
1189
1190 add_show_from_set (
1191 add_set_cmd ("hash", no_class, var_boolean, (char *)&hashmark,
1192 "Set display of activity while downloading a file.\nWhen enabled, a period \'.\' is displayed.",
1193 &setlist),
1194 &showlist);
1195
1196 add_show_from_set (
1197 add_set_cmd ("timeout", no_class, var_zinteger,
1198 (char *) &timeout,
1199 "Set timeout in seconds for remote MIPS serial I/O.",
1200 &setlist),
1201 &showlist);
1202
d9389f37 1203 add_show_from_set (
d80ff70c 1204 add_set_cmd ("remotelog", no_class, var_zinteger,
d9389f37
KH
1205 (char *) &monitor_log,
1206 "Set monitor activity log on(=1) or off(=0).",
1207 &setlist),
1208 &showlist);
1209
d80ff70c
KH
1210 add_show_from_set (
1211 add_set_cmd ("remotexon", no_class, var_zinteger,
1212 (char *) &tty_xon,
1213 "Set remote tty line XON control",
1214 &setlist),
1215 &showlist);
1216
1217 add_show_from_set (
1218 add_set_cmd ("remotexoff", no_class, var_zinteger,
1219 (char *) &tty_xoff,
1220 "Set remote tty line XOFF control",
1221 &setlist),
1222 &showlist);
1340861c
KH
1223
1224 add_com ("rombug <command>", class_obscure, rombug_command,
1225 "Send a command to the debug monitor.");
1226#if 0
1227 add_com ("connect", class_obscure, connect_command,
1228 "Connect the terminal directly up to a serial based command monitor.\nUse <CR>~. or <CR>~^D to break out.");
1229#endif
1230}