Line 27... |
Line 27... |
#include <string.h>
|
#include <string.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <signal.h>
|
#include <signal.h>
|
#include <stdarg.h>
|
#include <stdarg.h>
|
/* Added by CZ 24/05/01 */
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/select.h>
|
|
#include <sys/poll.h>
|
|
#include <fcntl.h>
|
#include <fcntl.h>
|
#include <netdb.h>
|
|
#include <netinet/tcp.h>
|
|
#include <inttypes.h>
|
|
|
|
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
#include <readline/readline.h>
|
#include <readline/readline.h>
|
#include <readline/history.h>
|
#include <readline/history.h>
|
#endif /* HAVE_LIBREADLINE */
|
#endif /* HAVE_LIBREADLINE */
|
Line 53... |
Line 43... |
#include "trace.h"
|
#include "trace.h"
|
#include "execute.h"
|
#include "execute.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "spr_defs.h"
|
#include "spr_defs.h"
|
#include "dma.h"
|
#include "dma.h"
|
|
#include "vapi.h"
|
|
|
#include "coff.h"
|
#include "coff.h"
|
|
|
/* Added by CZ 24/05/01 */
|
#include "gdbcomm.h"
|
#include "gdb.h"
|
|
#include <signal.h>
|
|
#include <errno.h>
|
|
typedef enum {
|
|
false = 0,
|
|
true = 1,
|
|
} Boolean;
|
|
unsigned int serverIP = 0;
|
|
unsigned int serverPort = 0;
|
|
unsigned int server_fd = 0;
|
|
unsigned int gdb_fd = 0;
|
|
void HandleServerSocket(Boolean);
|
|
void JTAGRequest(void);
|
|
void GDBRequest(void);
|
|
void ProtocolClean(int,int32_t);
|
|
static int gdb_read(void*,int);
|
|
static int gdb_write(void*,int);
|
|
void BlockJTAG(void);
|
|
|
|
/* CVS revision number. */
|
/* CVS revision number. */
|
const char rcsrev[] = "$Revision: 1.37 $";
|
const char rcsrev[] = "$Revision: 1.38 $";
|
|
|
/* Continuos run versus single step tracing switch. */
|
/* Continuos run versus single step tracing switch. */
|
int cont_run;
|
int cont_run;
|
|
|
/* History of execution */
|
/* History of execution */
|
Line 134... |
Line 107... |
free(p);
|
free(p);
|
#endif
|
#endif
|
}
|
}
|
}
|
}
|
|
|
/* Strip whitespace from the start and end of STRING. Return a pointer
|
void ctrl_c(signum)
|
into STRING. */
|
|
#ifndef whitespace
|
|
#define whitespace(a) ((a) == '\t' ? 1 : ((a) == ' '? 1 : 0))
|
|
#endif
|
|
|
|
char *
|
|
stripwhite (string)
|
|
char *string;
|
|
{
|
|
register char *s, *t;
|
|
|
|
for (s = string; whitespace (*s); s++)
|
|
;
|
|
|
|
if (*s == 0)
|
|
return (s);
|
|
|
|
t = s + strlen (s) - 1;
|
|
while (t > s && whitespace (*t))
|
|
t--;
|
|
*++t = '\0';
|
|
|
|
return s;
|
|
}
|
|
|
|
void
|
|
ctrl_c(signum)
|
|
int signum;
|
int signum;
|
{
|
{
|
extern int cpu_stalled; /* CZ from debug_interface */
|
extern int cpu_stalled; /* CZ from debug_interface */
|
cont_run = cpu_stalled ? 0 : 1;
|
cont_run = cpu_stalled ? 0 : 1;
|
config.sim.iprompt = 1;
|
config.sim.iprompt = 1;
|
cpu_stalled = 0;
|
cpu_stalled = 0;
|
signal(SIGINT, ctrl_c);
|
signal(SIGINT, ctrl_c);
|
}
|
}
|
|
|
void
|
void version()
|
version()
|
|
{
|
{
|
printf ("\n");
|
printf ("\n");
|
printf ("OpenRISC 1000 (OR16+OR32) Architectural Simulator, %s\n", rcsrev);
|
printf ("OpenRISC 1000 (OR16+OR32) Architectural Simulator, %s\n", rcsrev);
|
printf ("Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
|
printf ("Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
|
printf ("Copyright (C) 2000 Damjan Lampret, lampret@opencores.org\n");
|
printf ("Copyright (C) 2000 Damjan Lampret, lampret@opencores.org\n");
|
Line 218... |
Line 163... |
printf("help - available commands (this list)\n");
|
printf("help - available commands (this list)\n");
|
}
|
}
|
|
|
void debugmem( unsigned long from, unsigned long to );
|
void debugmem( unsigned long from, unsigned long to );
|
|
|
main(argc, argv)
|
/* Initalizes all devices and sim */
|
int argc;
|
void sim_init ()
|
char *argv[];
|
|
{
|
{
|
char *linestr;
|
|
char item1[500], b2[500], prev_str[500] = "";
|
|
char *redirstr;
|
|
int hush = 0;
|
|
unsigned long endaddr = 0xFFFFFFFF;
|
|
int first_prompt = 1;
|
|
int trace_fd = 0;
|
|
|
|
srand(getpid());
|
|
init_defconfig();
|
|
if (parse_args(argc, argv)) {
|
|
printf("Usage: %s [options] <filename>\n", argv[0]);
|
|
printf("Options:\n");
|
|
printf(" -v version and copyright note\n");
|
|
printf(" -i enable interactive command prompt\n");
|
|
printf(" -f or --file change script file [sim.cfg]\n");
|
|
printf(" --nosrv do not launch JTAG proxy server\n"); /* (CZ) */
|
|
printf(" --srv <n> launch JTAG proxy server on port <n>; [random]\n"); /* (CZ) */
|
|
printf(" --profile enable profiling\n");
|
|
exit(-1);
|
|
}
|
|
|
|
#ifdef HAVE_LIBREADLINE
|
|
initialize_readline (); /* Bind our completer. */
|
|
#endif
|
|
|
|
/* Read configuration file. */
|
|
read_script_file(config.script_file);
|
|
print_config();
|
|
init_labels();
|
init_labels();
|
init_breakpoints();
|
init_breakpoints();
|
signal(SIGINT, ctrl_c);
|
|
initstats();
|
initstats();
|
build_automata();
|
build_automata();
|
|
|
if(GDB_ENABLED) {
|
if(GDB_ENABLED) {
|
serverPort = config.debug.server_port;
|
serverPort = config.debug.server_port;
|
Line 310... |
Line 224... |
exit(1);
|
exit(1);
|
}
|
}
|
}
|
}
|
|
|
if(config.filename) {
|
if(config.filename) {
|
|
unsigned long endaddr = 0xFFFFFFFF;
|
endaddr = loadcode(config.filename, 0, 0); /* MM170901 always load at address zero. */
|
endaddr = loadcode(config.filename, 0, 0); /* MM170901 always load at address zero. */
|
if (endaddr == -1) {
|
if (endaddr == -1) {
|
fprintf(stderr, "Problems loading boot code.\n");
|
fprintf(stderr, "Problems loading boot code.\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
Line 329... |
Line 244... |
tick_reset();
|
tick_reset();
|
pm_reset();
|
pm_reset();
|
pic_reset();
|
pic_reset();
|
mc_reset();
|
mc_reset();
|
reset();
|
reset();
|
|
}
|
|
|
|
/* Display info about various modules */
|
|
void sim_info () {
|
|
itlb_status(-1);
|
|
dtlb_status(-1);
|
|
ic_info();
|
|
dc_info();
|
|
sprs_status();
|
|
|
|
if (config.cpu.bpb) bpb_info();
|
|
if (config.cpu.btic) btic_info();
|
|
if (config.uarts_enabled) uart_status();
|
|
if (config.dmas_enabled) dma_status();
|
|
if (config.ethernets_enabled) eth_status();
|
|
}
|
|
|
|
/* Cleanup */
|
|
void sim_done ()
|
|
{
|
|
if (config.sim.profile) {
|
|
extern int cycles;
|
|
fprintf(config.sim.fprof,"-%08X FFFFFFFF\n", cycles);
|
|
fclose(config.sim.fprof);
|
|
}
|
|
if (config.sim.exe_log) fclose(config.sim.fexe_log);
|
|
if (config.vapi.enabled) vapi_done ();
|
|
exit(0);
|
|
}
|
|
|
|
int main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
char *linestr;
|
|
char item1[500], b2[500], prev_str[500] = "";
|
|
char *redirstr;
|
|
int hush = 0;
|
|
int first_prompt = 1;
|
|
int trace_fd = 0;
|
|
|
|
srand(getpid());
|
|
init_defconfig();
|
|
if (parse_args(argc, argv)) {
|
|
printf("Usage: %s [options] <filename>\n", argv[0]);
|
|
printf("Options:\n");
|
|
printf(" -v version and copyright note\n");
|
|
printf(" -i enable interactive command prompt\n");
|
|
printf(" -f or --file change script file [sim.cfg]\n");
|
|
printf(" --nosrv do not launch JTAG proxy server\n"); /* (CZ) */
|
|
printf(" --srv <n> launch JTAG proxy server on port <n>; [random]\n"); /* (CZ) */
|
|
printf(" --profile enable profiling\n");
|
|
exit(-1);
|
|
}
|
|
|
|
#ifdef HAVE_LIBREADLINE
|
|
initialize_readline (); /* Bind our completer. */
|
|
#endif
|
|
|
|
/* Read configuration file. */
|
|
read_script_file(config.script_file);
|
|
print_config();
|
|
signal(SIGINT, ctrl_c);
|
|
sim_init ();
|
|
|
while(1) {
|
while(1) {
|
if (config.sim.iprompt) {
|
if (config.sim.iprompt) {
|
if(server_fd)
|
if (GDB_ENABLED && server_fd)
|
{
|
{
|
printf ("(sim) ");
|
printf ("(sim) ");
|
fflush(stdout);
|
fflush(stdout);
|
HandleServerSocket(true); /* block & check_stdin = true */
|
HandleServerSocket(true); /* block & check_stdin = true */
|
}
|
}
|
Line 390... |
Line 369... |
strcpy (&prev_str[0], linestr);
|
strcpy (&prev_str[0], linestr);
|
|
|
strtoken(linestr, item1, 1);
|
strtoken(linestr, item1, 1);
|
if (strcmp(item1, "q") == 0) { /* quit */
|
if (strcmp(item1, "q") == 0) { /* quit */
|
printf ("\n");
|
printf ("\n");
|
if (config.sim.profile) {
|
sim_done ();
|
extern int cycles;
|
|
fprintf(config.sim.fprof,"-%08X FFFFFFFF\n", cycles);
|
|
fclose(config.sim.fprof);
|
|
}
|
|
if (config.sim.exe_log)
|
|
fclose(config.sim.fexe_log);
|
|
exit(0);
|
|
} else
|
} else
|
if (strcmp(item1, "help") == 0) /* help */
|
if (strcmp(item1, "help") == 0) /* help */
|
help();
|
help();
|
else
|
else
|
if (strcmp(item1, "t") == 0) { /* trace */
|
if (strcmp(item1, "t") == 0) { /* trace */
|
Line 600... |
Line 572... |
} else {
|
} else {
|
i = strtoul(item2, NULL, 0);
|
i = strtoul(item2, NULL, 0);
|
printstats(i);
|
printstats(i);
|
}
|
}
|
} else
|
} else
|
if (strcmp(item1, "info") == 0) { /* configuration info */
|
if (strcmp(item1, "info") == 0) /* configuration info */
|
itlb_status(-1);
|
sim_info ();
|
dtlb_status(-1);
|
else
|
bpb_info();
|
|
btic_info();
|
|
ic_info();
|
|
dc_info();
|
|
uart_status();
|
|
sprs_status();
|
|
dma_status();
|
|
eth_status();
|
|
} else {
|
|
printf("%s: Unknown command.\n", linestr);
|
printf("%s: Unknown command.\n", linestr);
|
}
|
|
|
|
/* MM: 'run -1' means endless execution. */
|
/* MM: 'run -1' means endless execution. */
|
while(cont_run != 0) {
|
while(cont_run != 0) {
|
int debug_slowdown = DEBUG_SLOWDOWN;
|
int debug_slowdown = DEBUG_SLOWDOWN;
|
extern int cycle_delay; /* Added by CZ 27/05/01. Set during exception. */
|
extern int cycle_delay; /* Added by CZ 27/05/01. Set during exception. */
|
Line 630... |
Line 593... |
continue;
|
continue;
|
} else
|
} else
|
fprintf (stderr, "WARNING: CPU stalled and gdb connection not enabled.");
|
fprintf (stderr, "WARNING: CPU stalled and gdb connection not enabled.");
|
|
|
if (!testsprbits(SPR_PMR, SPR_PMR_DME | SPR_PMR_SME)) {
|
if (!testsprbits(SPR_PMR, SPR_PMR_DME | SPR_PMR_SME)) {
|
if(cycle_delay <= 0)
|
if(cycle_delay <= 0) {
|
{
|
|
unsigned int addr;
|
unsigned int addr;
|
if (cont_run > 0) cont_run--;
|
if (cont_run > 0) cont_run--;
|
if(fetch()) {
|
if(fetch()) {
|
cont_run = 0; /* memory breakpoint encountered */
|
cont_run = 0; /* memory breakpoint encountered */
|
break;
|
break;
|
Line 644... |
Line 606... |
|
|
/* If trace_fd is non zero, we want
|
/* If trace_fd is non zero, we want
|
to make sure that disassemble is called */
|
to make sure that disassemble is called */
|
|
|
decode_execute(&iqueue[0],trace_fd);
|
decode_execute(&iqueue[0],trace_fd);
|
if(trace_fd)
|
if(trace_fd) {
|
{
|
|
char sTemp[256];
|
char sTemp[256];
|
char sTemp2[256];
|
char sTemp2[256];
|
unsigned long value;
|
unsigned long value;
|
extern char *disassembled;
|
extern char *disassembled;
|
extern unsigned long reg[];
|
extern unsigned long reg[];
|
Line 676... |
Line 637... |
}
|
}
|
update_pc();
|
update_pc();
|
analysis();
|
analysis();
|
if (!hush)
|
if (!hush)
|
dumpreg();
|
dumpreg();
|
}
|
} else
|
else
|
|
cycle_delay--;
|
cycle_delay--;
|
|
|
pic_clock();
|
pic_clock();
|
dc_clock();
|
dc_clock();
|
ic_clock();
|
ic_clock();
|
|
if (!testsprbits(SPR_PMR, SPR_PMR_SME)) tick_clock();
|
}
|
}
|
if (!testsprbits(SPR_PMR, SPR_PMR_SME))
|
|
tick_clock();
|
|
pm_clock();
|
|
uart_clock();
|
|
dma_clock();
|
|
eth_clock();
|
|
if (config.sim.exe_log)
|
|
dump_exe_log();
|
|
|
|
/*if (config.vapi.enabled)
|
pm_clock();
|
vapi_check();*/
|
if (config.uarts_enabled) uart_clock();
|
|
if (config.dmas_enabled) dma_clock();
|
|
if (config.ethernets_enabled) eth_clock();
|
|
if (config.sim.exe_log) dump_exe_log();
|
|
if (config.vapi.enabled) vapi_check();
|
if (GDB_ENABLED && debug_slowdown-- == 0) {
|
if (GDB_ENABLED && debug_slowdown-- == 0) {
|
debug_slowdown = DEBUG_SLOWDOWN;
|
debug_slowdown = DEBUG_SLOWDOWN;
|
HandleServerSocket(false); /* block & check_stdin = false */
|
HandleServerSocket(false); /* block & check_stdin = false */
|
}
|
}
|
}
|
}
|
hush = 0;
|
hush = 0;
|
fflush(stdout);
|
fflush(stdout);
|
freopen("/dev/fd/0", "w+", stdout);
|
freopen("/dev/fd/0", "w+", stdout);
|
|
|
if (!config.sim.iprompt) { /* non-interactive quit */
|
if (!config.sim.iprompt) /* non-interactive quit */
|
if (config.sim.profile) {
|
sim_done();
|
extern int cycles;
|
|
fprintf(config.sim.fprof,"-%08X FFFFFFFF\n", cycles);
|
|
fclose(config.sim.fprof);
|
|
}
|
|
if (config.sim.exe_log)
|
|
fclose(config.sim.fexe_log);
|
|
exit(0);
|
|
}
|
|
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
if (linestr)
|
if (linestr)
|
free (linestr);
|
free (linestr);
|
#endif
|
#endif
|
|
|
}
|
}
|
exit(0);
|
sim_done();
|
}
|
}
|
|
|
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
char *command_generator ();
|
char *command_generator ();
|
char **sim_completion ();
|
char **sim_completion ();
|
Line 795... |
Line 745... |
|
|
/* If no names matched, then return NULL. */
|
/* If no names matched, then return NULL. */
|
return ((char *)NULL);
|
return ((char *)NULL);
|
}
|
}
|
|
|
char *
|
|
dupstr (s)
|
|
char *s;
|
|
{
|
|
char *r;
|
|
|
|
r = xmalloc (strlen (s) + 1);
|
|
strcpy (r, s);
|
|
return (r);
|
|
}
|
|
|
|
/* Repeats the last command. */
|
/* Repeats the last command. */
|
char *
|
char *
|
repeat_last_command ()
|
repeat_last_command ()
|
{
|
{
|
int offset = where_history ();
|
int offset = where_history ();
|
Line 843... |
Line 782... |
printf("%08x %s\n", _insn, disassembled);
|
printf("%08x %s\n", _insn, disassembled);
|
i += insn_len( iqueue[0].insn_index );
|
i += insn_len( iqueue[0].insn_index );
|
}
|
}
|
}
|
}
|
|
|
static int tcp_level = 0;
|
|
|
|
/* Added by CZ 24/05/01 */
|
|
int GetServerSocket(const char* name,const char* proto,int port)
|
|
{
|
|
struct servent *service;
|
|
struct protoent *protocol;
|
|
struct sockaddr_in sa;
|
|
struct hostent *hp;
|
|
int sockfd;
|
|
char myname[256];
|
|
int flags;
|
|
char sTemp[256];
|
|
|
|
/* First, get the protocol number of TCP */
|
|
if(!(protocol = getprotobyname(proto)))
|
|
{
|
|
sprintf(sTemp,"Unable to load protocol \"%s\"",proto);
|
|
perror(sTemp);
|
|
return 0;
|
|
}
|
|
tcp_level = protocol->p_proto; /* Save for later */
|
|
|
|
/* If we weren't passed a non standard port, get the port
|
|
from the services directory. */
|
|
if(!port)
|
|
{
|
|
if(service = getservbyname(name,protocol->p_name))
|
|
port = ntohs(service->s_port);
|
|
}
|
|
|
|
/* Create the socket using the TCP protocol */
|
|
if((sockfd = socket(PF_INET,SOCK_STREAM,protocol->p_proto)) < 0)
|
|
{
|
|
perror("Unable to create socket");
|
|
return 0;
|
|
}
|
|
|
|
flags = 1;
|
|
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0)
|
|
{
|
|
sprintf(sTemp,"Can not set SO_REUSEADDR option on socket %d",sockfd);
|
|
perror(sTemp);
|
|
close(sockfd);
|
|
return 0;
|
|
}
|
|
|
|
/* The server should also be non blocking. Get the current flags. */
|
|
if(fcntl(sockfd,F_GETFL,&flags) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to get flags for socket %d",sockfd);
|
|
perror(sTemp);
|
|
close(sockfd);
|
|
return 0;
|
|
}
|
|
|
|
/* Set the nonblocking flag */
|
|
if(fcntl(sockfd,F_SETFL, flags | O_NONBLOCK) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to set flags for socket %d to value 0x%08x",
|
|
sockfd,flags | O_NONBLOCK);
|
|
perror(sTemp);
|
|
close(sockfd);
|
|
return 0;
|
|
}
|
|
|
|
/* Find out what our address is */
|
|
memset(&sa,0,sizeof(struct sockaddr_in));
|
|
gethostname(myname,sizeof(myname));
|
|
if(!(hp = gethostbyname(myname)))
|
|
{
|
|
perror("Unable to read hostname");
|
|
close(sockfd);
|
|
return 0;
|
|
}
|
|
|
|
/* Bind our socket to the appropriate address */
|
|
sa.sin_family = hp->h_addrtype;
|
|
sa.sin_port = htons(port);
|
|
if(bind(sockfd,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to bind socket %d to port %d",sockfd,port);
|
|
perror(sTemp);
|
|
close(sockfd);
|
|
return 0;
|
|
}
|
|
serverIP = sa.sin_addr.s_addr;
|
|
flags = sizeof(struct sockaddr_in);
|
|
if(getsockname(sockfd,(struct sockaddr*)&sa,&flags) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to get socket information for socket %d",sockfd);
|
|
perror(sTemp);
|
|
close(sockfd);
|
|
return 0;
|
|
}
|
|
serverPort = ntohs(sa.sin_port);
|
|
|
|
/* Set the backlog to 1 connections */
|
|
if(listen(sockfd,1) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to set backlog on socket %d to %d",sockfd,1);
|
|
perror(sTemp);
|
|
close(sockfd);
|
|
return 0;
|
|
}
|
|
|
|
return sockfd;
|
|
}
|
|
|
|
void BlockJTAG()
|
|
{
|
|
struct pollfd fds[2];
|
|
int n = 0;
|
|
|
|
fds[n].fd = server_fd;
|
|
fds[n].events = POLLIN;
|
|
fds[n++].revents = 0;
|
|
if(gdb_fd)
|
|
{
|
|
fds[n].fd = gdb_fd;
|
|
fds[n].events = POLLIN;
|
|
fds[n++].revents = 0;
|
|
}
|
|
poll(fds,n,-1);
|
|
}
|
|
|
|
void HandleServerSocket(Boolean block)
|
|
{
|
|
struct pollfd fds[3];
|
|
int n = 0;
|
|
int timeout = block ? -1 : 0;
|
|
int server_index = -1;
|
|
int gdb_index = -1;
|
|
Boolean data_on_stdin = false;
|
|
int o_serv_fd = server_fd;
|
|
|
|
if(!o_serv_fd && !gdb_fd)
|
|
return;
|
|
|
|
if(o_serv_fd)
|
|
{
|
|
fds[n].fd = o_serv_fd;
|
|
fds[n].events = POLLIN;
|
|
fds[n++].revents = 0;
|
|
}
|
|
if(gdb_fd)
|
|
{
|
|
fds[n].fd = gdb_fd;
|
|
fds[n].events = POLLIN;
|
|
fds[n++].revents = 0;
|
|
}
|
|
if(block)
|
|
{
|
|
fds[n].fd = 0;
|
|
fds[n].events = POLLIN;
|
|
fds[n++].revents = 0;
|
|
}
|
|
|
|
while(!data_on_stdin)
|
|
{
|
|
switch(poll(fds,n,timeout))
|
|
{
|
|
case -1:
|
|
if(errno == EINTR)
|
|
continue;
|
|
perror("poll");
|
|
server_fd = 0;
|
|
break;
|
|
case 0: /* Nothing interesting going on */
|
|
data_on_stdin = true; /* Can only get here if nonblocking */
|
|
break;
|
|
default:
|
|
/* Make sure to handle the gdb port first! */
|
|
if((fds[0].revents && (gdb_fd && !o_serv_fd) ||
|
|
fds[1].revents && (server_fd && gdb_fd)))
|
|
{
|
|
int revents = o_serv_fd ? fds[1].revents : fds[0].revents;
|
|
|
|
if(revents & POLLIN)
|
|
GDBRequest();
|
|
else /* Error Occurred */
|
|
{
|
|
fprintf(stderr,"Received flags 0x%08x on gdb socket. Shutting down.\n",revents);
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
}
|
|
if(fds[0].revents && o_serv_fd)
|
|
{
|
|
if(fds[0].revents & POLLIN)
|
|
JTAGRequest();
|
|
else /* Error Occurred */
|
|
{
|
|
fprintf(stderr,"Received flags 0x%08x on server. Shutting down.\n",fds[0].revents);
|
|
close(o_serv_fd);
|
|
server_fd = 0;
|
|
serverPort = 0;
|
|
serverIP = 0;
|
|
}
|
|
}
|
|
if(fds[2].revents || (fds[1].revents && !gdb_fd))
|
|
data_on_stdin = true;
|
|
break;
|
|
} /* End of switch statement */
|
|
} /* End of while statement */
|
|
}
|
|
|
|
void JTAGRequest()
|
|
{
|
|
struct sockaddr_in sa;
|
|
struct sockaddr* addr = (struct sockaddr*)&sa;
|
|
int n = sizeof(struct sockaddr_in);
|
|
int fd = accept(server_fd,addr,&n);
|
|
int on_off = 0; /* Turn off Nagel's algorithm on the socket */
|
|
int flags;
|
|
char sTemp[256];
|
|
|
|
if(fd < 0)
|
|
{
|
|
/* This is valid, because a connection could have started,
|
|
and then terminated due to a protocol error or user
|
|
initiation before the accept could take place. */
|
|
if(errno != EWOULDBLOCK && errno != EAGAIN)
|
|
{
|
|
perror("accept");
|
|
close(server_fd);
|
|
server_fd = 0;
|
|
serverPort = 0;
|
|
serverIP = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(gdb_fd)
|
|
{
|
|
close(fd);
|
|
return;
|
|
}
|
|
|
|
if(fcntl(fd,F_GETFL,&flags) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to get flags for gdb socket %d",fd);
|
|
perror(sTemp);
|
|
close(fd);
|
|
return;
|
|
}
|
|
|
|
if(fcntl(fd,F_SETFL, flags | O_NONBLOCK) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to set flags for gdb socket %d to value 0x%08x",
|
|
fd,flags | O_NONBLOCK);
|
|
perror(sTemp);
|
|
close(fd);
|
|
return;
|
|
}
|
|
|
|
if(setsockopt(fd,tcp_level,TCP_NODELAY,&on_off,sizeof(int)) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",fd);
|
|
perror(sTemp);
|
|
close(fd);
|
|
return;
|
|
}
|
|
|
|
gdb_fd = fd;
|
|
}
|
|
|
|
void GDBRequest()
|
|
{
|
|
JTAGProxyWriteMessage msg_write;
|
|
JTAGProxyReadMessage msg_read;
|
|
JTAGProxyChainMessage msg_chain;
|
|
JTAGProxyWriteResponse resp_write;
|
|
JTAGProxyReadResponse resp_read;
|
|
JTAGProxyChainResponse resp_chain;
|
|
JTAGProxyBlockWriteMessage *msg_bwrite;
|
|
JTAGProxyBlockReadMessage msg_bread;
|
|
JTAGProxyBlockWriteResponse resp_bwrite;
|
|
JTAGProxyBlockReadResponse *resp_bread;
|
|
char *buf;
|
|
unsigned long long data;
|
|
int err = 0;
|
|
uint32_t command,length;
|
|
int len,i;
|
|
|
|
/* First, we must read the incomming command */
|
|
if(gdb_read(&command,sizeof(uint32_t)) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 1");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
return;
|
|
}
|
|
if(gdb_read(&length,sizeof(uint32_t)) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 2");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
return;
|
|
}
|
|
length = ntohl(length);
|
|
|
|
/* Now, verify the protocol and implement the command */
|
|
switch(ntohl(command))
|
|
{
|
|
case JTAG_COMMAND_WRITE:
|
|
if(length != sizeof(msg_write) - 8)
|
|
{
|
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
buf = (char*)&msg_write;
|
|
if(gdb_read(&buf[8],length) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 3");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
return;
|
|
}
|
|
msg_write.address = ntohl(msg_write.address);
|
|
msg_write.data_H = ntohl(msg_write.data_H);
|
|
msg_write.data_L = ntohl(msg_write.data_L);
|
|
err = DebugSetRegister(msg_write.address,msg_write.data_L);
|
|
resp_write.status = htonl(err);
|
|
if(gdb_write(&resp_write,sizeof(resp_write)) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 4");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
case JTAG_COMMAND_READ:
|
|
if(length != sizeof(msg_read) - 8)
|
|
{
|
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
buf = (char*)&msg_read;
|
|
if(gdb_read(&buf[8],length) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 5");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
return;
|
|
}
|
|
msg_read.address = ntohl(msg_read.address);
|
|
err = DebugGetRegister(msg_read.address,&resp_read.data_L);
|
|
resp_read.status = htonl(err);
|
|
resp_read.data_H = 0;
|
|
resp_read.data_L = htonl(resp_read.data_L);
|
|
if(gdb_write(&resp_read,sizeof(resp_read)) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 6");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
case JTAG_COMMAND_BLOCK_WRITE:
|
|
if(length < sizeof(JTAGProxyBlockWriteMessage)-8)
|
|
{
|
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
if(!(buf = (char*)malloc(8+length)))
|
|
{
|
|
ProtocolClean(length,JTAG_PROXY_OUT_OF_MEMORY);
|
|
return;
|
|
}
|
|
msg_bwrite = (JTAGProxyBlockWriteMessage*)buf;
|
|
if(gdb_read(&buf[8],length) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 5");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
free(buf);
|
|
return;
|
|
}
|
|
msg_bwrite->address = ntohl(msg_bwrite->address);
|
|
msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters);
|
|
for(i=0;i<msg_bwrite->nRegisters;i++)
|
|
{
|
|
int t_err = 0;
|
|
|
|
msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]);
|
|
t_err = DebugSetRegister(msg_bwrite->address+i,msg_bwrite->data[i]);
|
|
err = err ? err : t_err;
|
|
}
|
|
resp_bwrite.status = htonl(err);
|
|
free(buf);
|
|
buf = NULL;
|
|
msg_bwrite = NULL;
|
|
if(gdb_write(&resp_bwrite,sizeof(resp_bwrite)) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 4");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
case JTAG_COMMAND_BLOCK_READ:
|
|
if(length != sizeof(msg_bread) - 8)
|
|
{
|
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
buf = (char*)&msg_bread;
|
|
if(gdb_read(&buf[8],length) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 5");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
return;
|
|
}
|
|
msg_bread.address = ntohl(msg_bread.address);
|
|
msg_bread.nRegisters = ntohl(msg_bread.nRegisters);
|
|
len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1);
|
|
if(!(buf = (char*)malloc(len)))
|
|
{
|
|
ProtocolClean(0,JTAG_PROXY_OUT_OF_MEMORY);
|
|
return;
|
|
}
|
|
resp_bread = (JTAGProxyBlockReadResponse*)buf;
|
|
for(i=0;i<msg_bread.nRegisters;i++)
|
|
{
|
|
int t_err;
|
|
|
|
t_err = DebugGetRegister(msg_bread.address+i,&resp_bread->data[i]);
|
|
resp_bread->data[i] = htonl(resp_bread->data[i]);
|
|
err = err ? err : t_err;
|
|
}
|
|
resp_bread->status = htonl(err);
|
|
resp_bread->nRegisters = htonl(msg_bread.nRegisters);
|
|
if(gdb_write(resp_bread,len) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 6");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
free(buf);
|
|
return;
|
|
}
|
|
free(buf);
|
|
buf = NULL;
|
|
resp_bread = NULL;
|
|
break;
|
|
case JTAG_COMMAND_CHAIN:
|
|
if(length != sizeof(msg_chain) - 8)
|
|
{
|
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
|
return;
|
|
}
|
|
buf = (char*)&msg_chain;
|
|
if(gdb_read(&buf[8],sizeof(msg_chain)-8) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 7");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
return;
|
|
}
|
|
msg_chain.chain = htonl(msg_chain.chain);
|
|
err = DebugSetChain(msg_chain.chain);
|
|
resp_chain.status = htonl(err);
|
|
if(gdb_write(&resp_chain,sizeof(resp_chain)) < 0)
|
|
{
|
|
if(gdb_fd)
|
|
{
|
|
perror("gdb socket - 8");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
ProtocolClean(length,JTAG_PROXY_COMMAND_NOT_IMPLEMENTED);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ProtocolClean(int length,int32_t err)
|
|
{
|
|
char buf[4096];
|
|
|
|
err = htonl(err);
|
|
if((gdb_read(buf,length) < 0) ||
|
|
(gdb_write(&err,sizeof(err)) < 0) && gdb_fd)
|
|
{
|
|
perror("gdb socket - 9");
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
}
|
|
}
|
|
|
|
static int gdb_write(void* buf,int len)
|
|
{
|
|
int n;
|
|
char* w_buf = (char*)buf;
|
|
struct pollfd block;
|
|
|
|
while(len)
|
|
{
|
|
if((n = write(gdb_fd,w_buf,len)) < 0)
|
|
{
|
|
switch(errno)
|
|
{
|
|
case EWOULDBLOCK: /* or EAGAIN */
|
|
/* We've been called on a descriptor marked
|
|
for nonblocking I/O. We better simulate
|
|
blocking behavior. */
|
|
block.fd = gdb_fd;
|
|
block.events = POLLOUT;
|
|
block.revents = 0;
|
|
poll(&block,1,-1);
|
|
continue;
|
|
case EINTR:
|
|
continue;
|
|
case EPIPE:
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
return -1;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
len -= n;
|
|
w_buf += n;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int gdb_read(void* buf,int len)
|
|
{
|
|
int n;
|
|
char* r_buf = (char*)buf;
|
|
struct pollfd block;
|
|
|
|
while(len)
|
|
{
|
|
if((n = read(gdb_fd,r_buf,len)) < 0)
|
|
{
|
|
switch(errno)
|
|
{
|
|
case EWOULDBLOCK: /* or EAGAIN */
|
|
/* We've been called on a descriptor marked
|
|
for nonblocking I/O. We better simulate
|
|
blocking behavior. */
|
|
block.fd = gdb_fd;
|
|
block.events = POLLIN;
|
|
block.revents = 0;
|
|
poll(&block,1,-1);
|
|
continue;
|
|
case EINTR:
|
|
continue;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
else if(n == 0)
|
|
{
|
|
close(gdb_fd);
|
|
gdb_fd = 0;
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
len -= n;
|
|
r_buf += n;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
No newline at end of file
|
No newline at end of file
|