From 704deef2c0830b00aca6614989cf7944b38ebeba Mon Sep 17 00:00:00 2001 From: Jim Kingdon Date: Wed, 28 Jul 1993 06:45:35 +0000 Subject: [PATCH] * serial.h, ser-{unix,go32,tcp}.c: Add flush_input and send_break. * nindy-share/*, remote-nindy.c: Extensive hacking to make it conform to GDB conventions like using memcpy not bcopy, serial.h, etc. This is to make it host on Solaris, AIX, etc. * Makefile.in: Reflect removed nindy-share files. --- gdb/ChangeLog | 6 +- gdb/remote-nindy.c | 349 ++++++++++++++++++++++----------------------- gdb/ser-go32.c | 7 +- gdb/ser-tcp.c | 8 +- gdb/ser-unix.c | 42 ++++++ gdb/serial.h | 16 ++- 6 files changed, 244 insertions(+), 184 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 43e156c2eec..fa4cf8ddaac 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -2,7 +2,11 @@ Tue Jul 27 12:07:38 1993 Jim Kingdon (kingdon@lioth.cygnus.com) * remote-udi.c: Remove old comment about download not implemented. - * serial.h, ser-{unix,go32,tcp}.c: Add flush_input. + * serial.h, ser-{unix,go32,tcp}.c: Add flush_input and send_break. + * nindy-share/*, remote-nindy.c: Extensive hacking to make it + conform to GDB conventions like using memcpy not bcopy, serial.h, + etc. This is to make it host on Solaris, AIX, etc. + * Makefile.in: Reflect removed nindy-share files. * stack.c (print_frame_info): Revise comment about `pathological' case (there was a wrong FIXME about text labels; also asm() can diff --git a/gdb/remote-nindy.c b/gdb/remote-nindy.c index 55efac778da..dd027bfd72c 100644 --- a/gdb/remote-nindy.c +++ b/gdb/remote-nindy.c @@ -113,8 +113,11 @@ NINDY ROM monitor at the other end of the line. #include #include #include +#include "serial.h" +#if 0 #include "nindy-share/ttycntl.h" #include "nindy-share/demux.h" +#endif #include "nindy-share/env.h" #include "nindy-share/stop.h" @@ -139,7 +142,9 @@ char *nindy_ttyname; /* name of tty to talk to nindy on, or null */ #define TRUE 1 #define FALSE 0 -int nindy_fd = 0; /* Descriptor for I/O to NINDY */ +/* From nindy-share/nindy.c. */ +extern serial_t nindy_serial; + static int have_regs = 0; /* 1 iff regs read since i960 last halted */ static int regs_changed = 0; /* 1 iff regs were modified since last read */ @@ -157,55 +162,15 @@ nindy_fetch_registers PARAMS ((int)); static void nindy_store_registers PARAMS ((int)); -/* FIXME, we can probably use the normal terminal_inferior stuff here. - We have to do terminal_inferior and then set up the passthrough - settings initially. Thereafter, terminal_ours and terminal_inferior - will automatically swap the settings around for us. */ - -/* Restore TTY to normal operation */ - -static TTY_STRUCT orig_tty; /* TTY attributes before entering passthrough */ - -static void -restore_tty() -{ - ioctl( 0, TIOCSETN, &orig_tty ); -} - - -/* Recover from ^Z or ^C while remote process is running */ - -static void (*old_ctrlc)(); /* Signal handlers before entering passthrough */ - -#ifdef SIGTSTP -static void (*old_ctrlz)(); -#endif - -static -#ifdef USG -void -#endif -cleanup() -{ - restore_tty(); - signal(SIGINT, old_ctrlc); -#ifdef SIGTSTP - signal(SIGTSTP, old_ctrlz); -#endif - error("\n\nYou may need to reset the 80960 and/or reload your program.\n"); -} - -/* Clean up anything that needs cleaning when losing control. */ - static char *savename; static void nindy_close (quitting) int quitting; { - if (nindy_fd) - close (nindy_fd); - nindy_fd = 0; + if (nindy_serial != NULL) + SERIAL_CLOSE (nindy_serial); + nindy_serial = NULL; if (savename) free (savename); @@ -229,25 +194,24 @@ nindy_open (name, from_tty) nindy_close (0); - have_regs = regs_changed = 0; - dcache_init(); + have_regs = regs_changed = 0; + dcache_init(); - /* Allow user to interrupt the following -- we could hang if - * there's no NINDY at the other end of the remote tty. - */ - immediate_quit++; - nindy_fd = ninConnect( name, baud_rate? baud_rate: "9600", - nindy_initial_brk, !from_tty, nindy_old_protocol ); - immediate_quit--; + /* Allow user to interrupt the following -- we could hang if there's + no NINDY at the other end of the remote tty. */ + immediate_quit++; + ninConnect(name, baud_rate ? baud_rate : "9600", + nindy_initial_brk, !from_tty, nindy_old_protocol); + immediate_quit--; - if ( nindy_fd < 0 ){ - nindy_fd = 0; - error( "Can't open tty '%s'", name ); - } + if (nindy_serial == NULL) + { + perror_with_name (name); + } - savename = savestring (name, strlen (name)); - push_target (&nindy_ops); - target_fetch_registers(-1); + savename = savestring (name, strlen (name)); + push_target (&nindy_ops); + target_fetch_registers(-1); } /* User-initiated quit of nindy operations. */ @@ -307,6 +271,27 @@ nindy_resume (step, siggnal) have_regs = 0; ninGo( step ); } + +/* FIXME, we can probably use the normal terminal_inferior stuff here. + We have to do terminal_inferior and then set up the passthrough + settings initially. Thereafter, terminal_ours and terminal_inferior + will automatically swap the settings around for us. */ + +struct clean_up_tty_args { + serial_ttystate state; + serial_t serial; +}; + +static void +clean_up_tty (ptrarg) + PTR ptrarg; +{ + struct clean_up_tty_args *args = (struct clean_up_tty_args *) ptrarg; + SERIAL_SET_TTY_STATE (args->serial, args->state); + free (args->state); + warning ("\n\n\ +You may need to reset the 80960 and/or reload your program.\n"); +} /* Wait until the remote machine stops. While waiting, operate in passthrough * mode; i.e., pass everything NINDY sends to stdout, and everything from @@ -319,107 +304,120 @@ static int nindy_wait( status ) WAITTYPE *status; { - DEMUX_DECL; /* OS-dependent data needed by DEMUX... macros */ - char buf[500]; /* FIXME, what is "500" here? */ - int i, n; - unsigned char stop_exit; - unsigned char stop_code; - TTY_STRUCT tty; - long ip_value, fp_value, sp_value; /* Reg values from stop */ - - - WSETEXIT( (*status), 0 ); - - /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */ - - /* Save current tty attributes, set up signals to restore them. - */ - ioctl( 0, TIOCGETP, &orig_tty ); - old_ctrlc = signal( SIGINT, cleanup ); -#ifdef SIGTSTP - old_ctrlz = signal( SIGTSTP, cleanup ); -#endif - - /* Pass input from keyboard to NINDY as it arrives. - * NINDY will interpret and perform echo. - */ - tty = orig_tty; - TTY_NINDYTERM( tty ); - ioctl( 0, TIOCSETN, &tty ); - - while ( 1 ){ - /* Go to sleep until there's something for us on either - * the remote port or stdin. - */ - - DEMUX_WAIT( nindy_fd ); - - /* Pass input through to correct place */ + fd_set fds; + char buf[500]; /* FIXME, what is "500" here? */ + int i, n; + unsigned char stop_exit; + unsigned char stop_code; + struct clean_up_tty_args tty_args; + struct cleanup *old_cleanups; + long ip_value, fp_value, sp_value; /* Reg values from stop */ + + WSETEXIT( (*status), 0 ); + + /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */ + + /* Save current tty attributes, and restore them when done. */ + tty_args.serial = SERIAL_FDOPEN (0); + tty_args.state = SERIAL_GET_TTY_STATE (tty_args.serial); + old_cleanups = make_cleanup (clean_up_tty, &tty_args); + + /* Pass input from keyboard to NINDY as it arrives. NINDY will interpret + and perform echo. */ + /* This used to set CBREAK and clear ECHO and CRMOD. I hope this is close + enough. */ + SERIAL_RAW (tty_args.serial); + + while (1) + { + /* Wait for input on either the remote port or stdin. */ + FD_ZERO (&fds); + FD_SET (0, &fds); + FD_SET (nindy_serial->fd, &fds); + if (select (nindy_serial->fd + 1, &fds, 0, 0, 0) <= 0) + continue; + + /* Pass input through to correct place */ + if (FD_ISSET (0, &fds)) + { + /* Input on stdin */ + n = read (0, buf, sizeof (buf)); + if (n) + { + SERIAL_WRITE (nindy_serial, buf, n ); + } + } - n = DEMUX_READ( 0, buf, sizeof(buf) ); - if ( n ){ /* Input on stdin */ - write( nindy_fd, buf, n ); + if (FD_ISSET (nindy_serial->fd, &fds)) + { + /* Input on remote */ + n = read (nindy_serial->fd, buf, sizeof (buf)); + if (n) + { + /* Write out any characters in buffer preceding DLE */ + i = non_dle( buf, n ); + if ( i > 0 ) + { + write (1, buf, i); } - n = DEMUX_READ( nindy_fd, buf, sizeof(buf) ); - if ( n ){ /* Input on remote */ - /* Write out any characters in buffer preceding DLE */ - i = non_dle( buf, n ); - if ( i > 0 ){ - write( 1, buf, i ); - } - - if ( i != n ){ - /* There *was* a DLE in the buffer */ - stop_exit = ninStopWhy( &stop_code, - &ip_value, &fp_value, &sp_value); - if ( !stop_exit && (stop_code==STOP_SRQ) ){ - immediate_quit++; - ninSrq(); - immediate_quit--; - } else { - /* Get out of loop */ - supply_register (IP_REGNUM, - (char *)&ip_value); - supply_register (FP_REGNUM, - (char *)&fp_value); - supply_register (SP_REGNUM, - (char *)&sp_value); - break; - } - } + if (i != n) + { + /* There *was* a DLE in the buffer */ + stop_exit = ninStopWhy(&stop_code, + &ip_value, &fp_value, &sp_value); + if (!stop_exit && (stop_code == STOP_SRQ)) + { + immediate_quit++; + ninSrq(); + immediate_quit--; + } + else + { + /* Get out of loop */ + supply_register (IP_REGNUM, + (char *)&ip_value); + supply_register (FP_REGNUM, + (char *)&fp_value); + supply_register (SP_REGNUM, + (char *)&sp_value); + break; + } } + } } + } - signal( SIGINT, old_ctrlc ); -#ifdef SIGTSTP - signal( SIGTSTP, old_ctrlz ); -#endif - restore_tty(); - - if ( stop_exit ){ /* User program exited */ - WSETEXIT( (*status), stop_code ); - } else { /* Fault or trace */ - switch (stop_code){ - case STOP_GDB_BPT: - case TRACE_STEP: - /* Make it look like a VAX trace trap */ - stop_code = SIGTRAP; - break; - default: - /* The target is not running Unix, and its - faults/traces do not map nicely into Unix signals. - Make sure they do not get confused with Unix signals - by numbering them with values higher than the highest - legal Unix signal. code in i960_print_fault(), - called via PRINT_RANDOM_SIGNAL, will interpret the - value. */ - stop_code += NSIG; - break; - } - WSETSTOP( (*status), stop_code ); + do_cleanups (old_cleanups); + + if (stop_exit) + { + /* User program exited */ + WSETEXIT ((*status), stop_code); + } + else + { + /* Fault or trace */ + switch (stop_code) + { + case STOP_GDB_BPT: + case TRACE_STEP: + /* Breakpoint or single stepping. */ + stop_code = SIGTRAP; + break; + default: + /* The target is not running Unix, and its faults/traces do + not map nicely into Unix signals. Make sure they do not + get confused with Unix signals by numbering them with + values higher than the highest legal Unix signal. code + in i960_print_fault(), called via PRINT_RANDOM_SIGNAL, + will interpret the value. */ + stop_code += NSIG; + break; } - return inferior_pid; + WSETSTOP ((*status), stop_code); + } + return inferior_pid; } /* Read the remote registers into the block REGS. */ @@ -446,11 +444,11 @@ nindy_fetch_registers(regno) ninRegsGet( (char *) &nindy_regs ); immediate_quit--; - bcopy (nindy_regs.local_regs, ®isters[REGISTER_BYTE (R0_REGNUM)], 16*4); - bcopy (nindy_regs.global_regs, ®isters[REGISTER_BYTE (G0_REGNUM)], 16*4); - bcopy (nindy_regs.pcw_acw, ®isters[REGISTER_BYTE (PCW_REGNUM)], 2*4); - bcopy (nindy_regs.ip, ®isters[REGISTER_BYTE (IP_REGNUM)], 1*4); - bcopy (nindy_regs.tcw, ®isters[REGISTER_BYTE (TCW_REGNUM)], 1*4); + memcpy (®isters[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16*4); + memcpy (®isters[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4); + memcpy (®isters[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2*4); + memcpy (®isters[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1*4); + memcpy (®isters[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 1*4); for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) { dub = unpack_double (builtin_type_double, &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)], @@ -478,11 +476,11 @@ nindy_store_registers(regno) int regnum, inv; double dub; - bcopy (®isters[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16*4); - bcopy (®isters[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4); - bcopy (®isters[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2*4); - bcopy (®isters[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1*4); - bcopy (®isters[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 1*4); + memcpy (nindy_regs.local_regs, ®isters[REGISTER_BYTE (R0_REGNUM)], 16*4); + memcpy (nindy_regs.global_regs, ®isters[REGISTER_BYTE (G0_REGNUM)], 16*4); + memcpy (nindy_regs.pcw_acw, ®isters[REGISTER_BYTE (PCW_REGNUM)], 2*4); + memcpy (nindy_regs.ip, ®isters[REGISTER_BYTE (IP_REGNUM)], 1*4); + memcpy (nindy_regs.tcw, ®isters[REGISTER_BYTE (TCW_REGNUM)], 1*4); /* Float regs. Only works on IEEE_FLOAT hosts. FIXME! */ for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) { ieee_extended_to_double (&ext_format_i960, @@ -493,8 +491,7 @@ nindy_store_registers(regno) This mostly works but not quite. */ dub = unpack_double (builtin_type_double, (char *)&dub, &inv); /* dub now in target byte order */ - bcopy ((char *)&dub, &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)], - 8); + memcpy (&nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)], &dub, 8); } immediate_quit++; @@ -565,7 +562,7 @@ nindy_xfer_inferior_memory(memaddr, myaddr, len, write, target) /* Copy data to be written over corresponding part of buffer */ - bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); + memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); /* Write the entire buffer. */ @@ -590,7 +587,7 @@ nindy_xfer_inferior_memory(memaddr, myaddr, len, write, target) } /* Copy appropriate bytes out of the buffer. */ - bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); + memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); } return len; } @@ -808,13 +805,15 @@ reset_command(args, from_tty) char *args; int from_tty; { - if ( !nindy_fd ){ - error( "No target system to reset -- use 'target nindy' command."); - } - if ( query("Really reset the target system?",0,0) ){ - send_break( nindy_fd ); - tty_flush( nindy_fd ); - } + if (nindy_serial == NULL) + { + error( "No target system to reset -- use 'target nindy' command."); + } + if ( query("Really reset the target system?",0,0) ) + { + SERIAL_SEND_BREAK (nindy_serial); + tty_flush (nindy_serial); + } } void diff --git a/gdb/ser-go32.c b/gdb/ser-go32.c index ff1bdf11930..905526ddc18 100644 --- a/gdb/ser-go32.c +++ b/gdb/ser-go32.c @@ -267,10 +267,9 @@ go32_open (scb, name) } static int -go32_flush_output (scb) +go32_noop (scb) serial_t scb; { - /* No need to flush, because there is no buffering. */ return 0; } @@ -378,7 +377,9 @@ static struct serial_ops go32_ops = go32_close, go32_readchar, go32_write, - go32_flush_output, + go32_noop, /* flush output */ + go32_noop, /* flush input */ + go32_noop, /* send break -- currently used only for nindy */ go32_raw, go32_get_tty_state, go32_set_tty_state, diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c index 6ff79aa3d4a..f492bc13ccd 100644 --- a/gdb/ser-tcp.c +++ b/gdb/ser-tcp.c @@ -141,11 +141,9 @@ tcp_set_tty_state(scb, ttystate) } static int -tcp_flush_output (scb) +tcp_return_0 (scb) serial_t scb; { - /* This is only used by utils.c on stdout, so it doesn't need to work - for tcp. */ return 0; } @@ -309,7 +307,9 @@ static struct serial_ops tcp_ops = tcp_close, tcp_readchar, tcp_write, - tcp_flush_output, + tcp_return_0, /* flush output */ + tcp_return_0, /* flush input */ + tcp_return_0, /* send break */ tcp_raw, tcp_get_tty_state, tcp_set_tty_state, diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c index 5f07adec0c5..1f8d738f70a 100644 --- a/gdb/ser-unix.c +++ b/gdb/ser-unix.c @@ -326,6 +326,46 @@ hardwire_flush_output (scb) #endif } +static int +hardwire_flush_input (scb) + serial_t scb; +{ +#ifdef HAVE_TERMIOS + return tcflush (scb->fd, TCIFLUSH); +#endif + +#ifdef HAVE_TERMIO + return ioctl (scb->fd, TCFLSH, 0); +#endif + +#ifdef HAVE_SGTTY + /* This flushes both input and output, but we can't do better. */ + return ioctl (scb->fd, TIOCFLUSH, 0); +#endif +} + +static int +hardwire_send_break (scb) + serial_t scb; +{ + int status; + +#ifdef HAVE_TERMIOS + return tcsendbreak (scb->fd, 0); +#endif + +#ifdef HAVE_TERMIO + return ioctl (scb->fd, TCSBRK, 0); +#endif + +#ifdef HAVE_SGTTY + status = ioctl (scb->fd, TIOCSBRK, 0); + usleep (250000); + status = ioctl (scb->fd, TIOCCBRK, 0); + return status; +#endif +} + static void hardwire_raw(scb) serial_t scb; @@ -607,6 +647,8 @@ static struct serial_ops hardwire_ops = hardwire_readchar, hardwire_write, hardwire_flush_output, + hardwire_flush_input, + hardwire_send_break, hardwire_raw, hardwire_get_tty_state, hardwire_set_tty_state, diff --git a/gdb/serial.h b/gdb/serial.h index 630ed43b1f9..a9dba272125 100644 --- a/gdb/serial.h +++ b/gdb/serial.h @@ -42,6 +42,8 @@ struct serial_ops { int (*readchar) PARAMS ((serial_t, int timeout)); int (*write) PARAMS ((serial_t, const char *str, int len)); int (*flush_output) PARAMS ((serial_t)); + int (*flush_input) PARAMS ((serial_t)); + int (*send_break) PARAMS ((serial_t)); void (*go_raw) PARAMS ((serial_t)); serial_ttystate (*get_tty_state) PARAMS ((serial_t)); int (*set_tty_state) PARAMS ((serial_t, serial_ttystate)); @@ -72,11 +74,23 @@ serial_t serial_fdopen PARAMS ((int fd)); #define SERIAL_FDOPEN(FD) serial_fdopen(FD) -/* Flush pending output. */ +/* Flush pending output. Might also flush input (if this system can't flush + only output). */ #define SERIAL_FLUSH_OUTPUT(SERIAL_T) \ ((SERIAL_T)->ops->flush_output((SERIAL_T))) +/* Flush pending input. Might also flush output (if this system can't flush + only input). */ + +#define SERIAL_FLUSH_INPUT(SERIAL_T)\ + ((*(SERIAL_T)->ops->flush_input) ((SERIAL_T))) + +/* Send a break between 0.25 and 0.5 seconds long. */ + +#define SERIAL_SEND_BREAK(SERIAL_T) \ + ((*(SERIAL_T)->ops->send_break) (SERIAL_T)) + /* Turn the port into raw mode. */ #define SERIAL_RAW(SERIAL_T) (SERIAL_T)->ops->go_raw((SERIAL_T)) -- 2.30.2