/* gdbcomm.c -- Communication routines for gdb
|
/* gdbcomm.c -- Communication routines for gdb
|
Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
|
Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
|
Code copied from toplevel.c
|
Code copied from toplevel.c
|
|
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
|
|
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
(at your option) any later version.
|
(at your option) any later version.
|
|
|
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU General Public License for more details.
|
GNU General Public License for more details.
|
|
|
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
*/
|
*/
|
|
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <sys/stat.h>
|
#include <sys/stat.h>
|
#include <sys/types.h>
|
#include <sys/types.h>
|
#include <sys/socket.h>
|
#include <sys/socket.h>
|
#include <netinet/in.h>
|
#include <netinet/in.h>
|
#include <sys/select.h>
|
#include <sys/select.h>
|
#include <sys/poll.h>
|
#include <sys/poll.h>
|
#include <fcntl.h>
|
#include <fcntl.h>
|
#include <netdb.h>
|
#include <netdb.h>
|
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
#include <inttypes.h>
|
|
|
|
#include "gdb.h"
|
#include "gdb.h"
|
#include "gdbcomm.h"
|
#include "gdbcomm.h"
|
#include "vapi.h"
|
#include "vapi.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
|
|
static unsigned int serverIP = 0;
|
static unsigned int serverIP = 0;
|
static unsigned int serverPort = 0;
|
static unsigned int serverPort = 0;
|
static unsigned int server_fd = 0;
|
static unsigned int server_fd = 0;
|
static unsigned int gdb_fd = 0;
|
static unsigned int gdb_fd = 0;
|
|
|
static int tcp_level = 0;
|
static int tcp_level = 0;
|
|
|
/* Added by CZ 24/05/01 */
|
/* Added by CZ 24/05/01 */
|
int GetServerSocket(const char* name,const char* proto,int port)
|
int GetServerSocket(const char* name,const char* proto,int port)
|
{
|
{
|
struct servent *service;
|
struct servent *service;
|
struct protoent *protocol;
|
struct protoent *protocol;
|
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
struct hostent *hp;
|
struct hostent *hp;
|
int sockfd;
|
int sockfd;
|
char myname[256];
|
char myname[256];
|
int flags;
|
int flags;
|
char sTemp[256];
|
char sTemp[256];
|
|
|
/* First, get the protocol number of TCP */
|
/* First, get the protocol number of TCP */
|
if(!(protocol = getprotobyname(proto)))
|
if(!(protocol = getprotobyname(proto)))
|
{
|
{
|
sprintf(sTemp,"Unable to load protocol \"%s\"",proto);
|
sprintf(sTemp,"Unable to load protocol \"%s\"",proto);
|
perror(sTemp);
|
perror(sTemp);
|
return 0;
|
return 0;
|
}
|
}
|
tcp_level = protocol->p_proto; /* Save for later */
|
tcp_level = protocol->p_proto; /* Save for later */
|
|
|
/* If we weren't passed a non standard port, get the port
|
/* If we weren't passed a non standard port, get the port
|
from the services directory. */
|
from the services directory. */
|
if(!port)
|
if(!port)
|
{
|
{
|
if(service = getservbyname(name,protocol->p_name))
|
if(service = getservbyname(name,protocol->p_name))
|
port = ntohs(service->s_port);
|
port = ntohs(service->s_port);
|
}
|
}
|
|
|
/* Create the socket using the TCP protocol */
|
/* Create the socket using the TCP protocol */
|
if((sockfd = socket(PF_INET,SOCK_STREAM,protocol->p_proto)) < 0)
|
if((sockfd = socket(PF_INET,SOCK_STREAM,protocol->p_proto)) < 0)
|
{
|
{
|
perror("Unable to create socket");
|
perror("Unable to create socket");
|
return 0;
|
return 0;
|
}
|
}
|
|
|
flags = 1;
|
flags = 1;
|
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0)
|
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);
|
sprintf(sTemp,"Can not set SO_REUSEADDR option on socket %d",sockfd);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* The server should also be non blocking. Get the current flags. */
|
/* The server should also be non blocking. Get the current flags. */
|
if(fcntl(sockfd,F_GETFL,&flags) < 0)
|
if(fcntl(sockfd,F_GETFL,&flags) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to get flags for socket %d",sockfd);
|
sprintf(sTemp,"Unable to get flags for socket %d",sockfd);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Set the nonblocking flag */
|
/* Set the nonblocking flag */
|
if(fcntl(sockfd,F_SETFL, flags | O_NONBLOCK) < 0)
|
if(fcntl(sockfd,F_SETFL, flags | O_NONBLOCK) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to set flags for socket %d to value 0x%08x",
|
sprintf(sTemp,"Unable to set flags for socket %d to value 0x%08x",
|
sockfd,flags | O_NONBLOCK);
|
sockfd,flags | O_NONBLOCK);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Find out what our address is */
|
/* Find out what our address is */
|
memset(&sa,0,sizeof(struct sockaddr_in));
|
memset(&sa,0,sizeof(struct sockaddr_in));
|
gethostname(myname,sizeof(myname));
|
gethostname(myname,sizeof(myname));
|
if(!(hp = gethostbyname(myname)))
|
if(!(hp = gethostbyname(myname)))
|
{
|
{
|
perror("Unable to read hostname");
|
perror("Unable to read hostname");
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Bind our socket to the appropriate address */
|
/* Bind our socket to the appropriate address */
|
sa.sin_family = hp->h_addrtype;
|
sa.sin_family = hp->h_addrtype;
|
sa.sin_port = htons(port);
|
sa.sin_port = htons(port);
|
if(bind(sockfd,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)) < 0)
|
if(bind(sockfd,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to bind socket %d to port %d",sockfd,port);
|
sprintf(sTemp,"Unable to bind socket %d to port %d",sockfd,port);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
serverIP = sa.sin_addr.s_addr;
|
serverIP = sa.sin_addr.s_addr;
|
flags = sizeof(struct sockaddr_in);
|
flags = sizeof(struct sockaddr_in);
|
if(getsockname(sockfd,(struct sockaddr*)&sa,&flags) < 0)
|
if(getsockname(sockfd,(struct sockaddr*)&sa,&flags) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to get socket information for socket %d",sockfd);
|
sprintf(sTemp,"Unable to get socket information for socket %d",sockfd);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
serverPort = ntohs(sa.sin_port);
|
serverPort = ntohs(sa.sin_port);
|
|
|
/* Set the backlog to 1 connections */
|
/* Set the backlog to 1 connections */
|
if(listen(sockfd,1) < 0)
|
if(listen(sockfd,1) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to set backlog on socket %d to %d",sockfd,1);
|
sprintf(sTemp,"Unable to set backlog on socket %d to %d",sockfd,1);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
return sockfd;
|
return sockfd;
|
}
|
}
|
|
|
void BlockJTAG()
|
void BlockJTAG()
|
{
|
{
|
struct pollfd fds[2];
|
struct pollfd fds[2];
|
int n = 0;
|
int n = 0;
|
|
|
fds[n].fd = server_fd;
|
fds[n].fd = server_fd;
|
fds[n].events = POLLIN;
|
fds[n].events = POLLIN;
|
fds[n++].revents = 0;
|
fds[n++].revents = 0;
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
fds[n].fd = gdb_fd;
|
fds[n].fd = gdb_fd;
|
fds[n].events = POLLIN;
|
fds[n].events = POLLIN;
|
fds[n++].revents = 0;
|
fds[n++].revents = 0;
|
}
|
}
|
poll(fds,n,-1);
|
poll(fds,n,-1);
|
}
|
}
|
|
|
void HandleServerSocket(Boolean block)
|
void HandleServerSocket(Boolean block)
|
{
|
{
|
struct pollfd fds[3];
|
struct pollfd fds[3];
|
int n = 0;
|
int n = 0;
|
int timeout = block ? -1 : 0;
|
int timeout = block ? -1 : 0;
|
int server_index = -1;
|
int server_index = -1;
|
int gdb_index = -1;
|
int gdb_index = -1;
|
Boolean data_on_stdin = false;
|
Boolean data_on_stdin = false;
|
int o_serv_fd = server_fd;
|
int o_serv_fd = server_fd;
|
|
|
if(!o_serv_fd && !gdb_fd)
|
if(!o_serv_fd && !gdb_fd)
|
return;
|
return;
|
|
|
if(o_serv_fd)
|
if(o_serv_fd)
|
{
|
{
|
fds[n].fd = o_serv_fd;
|
fds[n].fd = o_serv_fd;
|
fds[n].events = POLLIN;
|
fds[n].events = POLLIN;
|
fds[n++].revents = 0;
|
fds[n++].revents = 0;
|
}
|
}
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
fds[n].fd = gdb_fd;
|
fds[n].fd = gdb_fd;
|
fds[n].events = POLLIN;
|
fds[n].events = POLLIN;
|
fds[n++].revents = 0;
|
fds[n++].revents = 0;
|
}
|
}
|
if(block)
|
if(block)
|
{
|
{
|
fds[n].fd = 0;
|
fds[n].fd = 0;
|
fds[n].events = POLLIN;
|
fds[n].events = POLLIN;
|
fds[n++].revents = 0;
|
fds[n++].revents = 0;
|
}
|
}
|
|
|
while(!data_on_stdin)
|
while(!data_on_stdin)
|
{
|
{
|
switch(poll(fds,n,timeout))
|
switch(poll(fds,n,timeout))
|
{
|
{
|
case -1:
|
case -1:
|
if(errno == EINTR)
|
if(errno == EINTR)
|
continue;
|
continue;
|
perror("poll");
|
perror("poll");
|
server_fd = 0;
|
server_fd = 0;
|
break;
|
break;
|
case 0: /* Nothing interesting going on */
|
case 0: /* Nothing interesting going on */
|
data_on_stdin = true; /* Can only get here if nonblocking */
|
data_on_stdin = true; /* Can only get here if nonblocking */
|
break;
|
break;
|
default:
|
default:
|
/* Make sure to handle the gdb port first! */
|
/* Make sure to handle the gdb port first! */
|
if((fds[0].revents && (gdb_fd && !o_serv_fd) ||
|
if((fds[0].revents && (gdb_fd && !o_serv_fd) ||
|
fds[1].revents && (server_fd && gdb_fd)))
|
fds[1].revents && (server_fd && gdb_fd)))
|
{
|
{
|
int revents = o_serv_fd ? fds[1].revents : fds[0].revents;
|
int revents = o_serv_fd ? fds[1].revents : fds[0].revents;
|
|
|
if(revents & POLLIN)
|
if(revents & POLLIN)
|
GDBRequest();
|
GDBRequest();
|
else /* Error Occurred */
|
else /* Error Occurred */
|
{
|
{
|
fprintf(stderr,"Received flags 0x%08x on gdb socket. Shutting down.\n",revents);
|
fprintf(stderr,"Received flags 0x%08x on gdb socket. Shutting down.\n",revents);
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
}
|
}
|
if(fds[0].revents && o_serv_fd)
|
if(fds[0].revents && o_serv_fd)
|
{
|
{
|
if(fds[0].revents & POLLIN)
|
if(fds[0].revents & POLLIN)
|
JTAGRequest();
|
JTAGRequest();
|
else /* Error Occurred */
|
else /* Error Occurred */
|
{
|
{
|
fprintf(stderr,"Received flags 0x%08x on server. Shutting down.\n",fds[0].revents);
|
fprintf(stderr,"Received flags 0x%08x on server. Shutting down.\n",fds[0].revents);
|
close(o_serv_fd);
|
close(o_serv_fd);
|
server_fd = 0;
|
server_fd = 0;
|
serverPort = 0;
|
serverPort = 0;
|
serverIP = 0;
|
serverIP = 0;
|
}
|
}
|
}
|
}
|
if(fds[2].revents || (fds[1].revents && !gdb_fd))
|
if(fds[2].revents || (fds[1].revents && !gdb_fd))
|
data_on_stdin = true;
|
data_on_stdin = true;
|
break;
|
break;
|
} /* End of switch statement */
|
} /* End of switch statement */
|
} /* End of while statement */
|
} /* End of while statement */
|
}
|
}
|
|
|
void JTAGRequest()
|
void JTAGRequest()
|
{
|
{
|
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
struct sockaddr* addr = (struct sockaddr*)&sa;
|
struct sockaddr* addr = (struct sockaddr*)&sa;
|
int n = sizeof(struct sockaddr_in);
|
int n = sizeof(struct sockaddr_in);
|
int fd = accept(server_fd,addr,&n);
|
int fd = accept(server_fd,addr,&n);
|
int on_off = 0; /* Turn off Nagel's algorithm on the socket */
|
int on_off = 0; /* Turn off Nagel's algorithm on the socket */
|
int flags;
|
int flags;
|
char sTemp[256];
|
char sTemp[256];
|
|
|
if(fd < 0)
|
if(fd < 0)
|
{
|
{
|
/* This is valid, because a connection could have started,
|
/* This is valid, because a connection could have started,
|
and then terminated due to a protocol error or user
|
and then terminated due to a protocol error or user
|
initiation before the accept could take place. */
|
initiation before the accept could take place. */
|
if(errno != EWOULDBLOCK && errno != EAGAIN)
|
if(errno != EWOULDBLOCK && errno != EAGAIN)
|
{
|
{
|
perror("accept");
|
perror("accept");
|
close(server_fd);
|
close(server_fd);
|
server_fd = 0;
|
server_fd = 0;
|
serverPort = 0;
|
serverPort = 0;
|
serverIP = 0;
|
serverIP = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
|
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
close(fd);
|
close(fd);
|
return;
|
return;
|
}
|
}
|
|
|
if(fcntl(fd,F_GETFL,&flags) < 0)
|
if(fcntl(fd,F_GETFL,&flags) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to get flags for gdb socket %d",fd);
|
sprintf(sTemp,"Unable to get flags for gdb socket %d",fd);
|
perror(sTemp);
|
perror(sTemp);
|
close(fd);
|
close(fd);
|
return;
|
return;
|
}
|
}
|
|
|
if(fcntl(fd,F_SETFL, flags | O_NONBLOCK) < 0)
|
if(fcntl(fd,F_SETFL, flags | O_NONBLOCK) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to set flags for gdb socket %d to value 0x%08x",
|
sprintf(sTemp,"Unable to set flags for gdb socket %d to value 0x%08x",
|
fd,flags | O_NONBLOCK);
|
fd,flags | O_NONBLOCK);
|
perror(sTemp);
|
perror(sTemp);
|
close(fd);
|
close(fd);
|
return;
|
return;
|
}
|
}
|
|
|
if(setsockopt(fd,tcp_level,TCP_NODELAY,&on_off,sizeof(int)) < 0)
|
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);
|
sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",fd);
|
perror(sTemp);
|
perror(sTemp);
|
close(fd);
|
close(fd);
|
return;
|
return;
|
}
|
}
|
|
|
gdb_fd = fd;
|
gdb_fd = fd;
|
}
|
}
|
|
|
void GDBRequest()
|
void GDBRequest()
|
{
|
{
|
JTAGProxyWriteMessage msg_write;
|
JTAGProxyWriteMessage msg_write;
|
JTAGProxyReadMessage msg_read;
|
JTAGProxyReadMessage msg_read;
|
JTAGProxyChainMessage msg_chain;
|
JTAGProxyChainMessage msg_chain;
|
JTAGProxyWriteResponse resp_write;
|
JTAGProxyWriteResponse resp_write;
|
JTAGProxyReadResponse resp_read;
|
JTAGProxyReadResponse resp_read;
|
JTAGProxyChainResponse resp_chain;
|
JTAGProxyChainResponse resp_chain;
|
JTAGProxyBlockWriteMessage *msg_bwrite;
|
JTAGProxyBlockWriteMessage *msg_bwrite;
|
JTAGProxyBlockReadMessage msg_bread;
|
JTAGProxyBlockReadMessage msg_bread;
|
JTAGProxyBlockWriteResponse resp_bwrite;
|
JTAGProxyBlockWriteResponse resp_bwrite;
|
JTAGProxyBlockReadResponse *resp_bread;
|
JTAGProxyBlockReadResponse *resp_bread;
|
char *buf;
|
char *buf;
|
unsigned long long data;
|
unsigned long long data;
|
int err = 0;
|
int err = 0;
|
uint32_t command,length;
|
uint32_t command,length;
|
int len,i;
|
int len,i;
|
|
|
/* First, we must read the incomming command */
|
/* First, we must read the incomming command */
|
if(gdb_read(&command,sizeof(uint32_t)) < 0)
|
if(gdb_read(&command,sizeof(uint32_t)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 1");
|
perror("gdb socket - 1");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
if(gdb_read(&length,sizeof(uint32_t)) < 0)
|
if(gdb_read(&length,sizeof(uint32_t)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 2");
|
perror("gdb socket - 2");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
length = ntohl(length);
|
length = ntohl(length);
|
|
|
/* Now, verify the protocol and implement the command */
|
/* Now, verify the protocol and implement the command */
|
switch(ntohl(command))
|
switch(ntohl(command))
|
{
|
{
|
case JTAG_COMMAND_WRITE:
|
case JTAG_COMMAND_WRITE:
|
if(length != sizeof(msg_write) - 8)
|
if(length != sizeof(msg_write) - 8)
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
return;
|
return;
|
}
|
}
|
buf = (char*)&msg_write;
|
buf = (char*)&msg_write;
|
if(gdb_read(&buf[8],length) < 0)
|
if(gdb_read(&buf[8],length) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 3");
|
perror("gdb socket - 3");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
msg_write.address = ntohl(msg_write.address);
|
msg_write.address = ntohl(msg_write.address);
|
msg_write.data_H = ntohl(msg_write.data_H);
|
msg_write.data_H = ntohl(msg_write.data_H);
|
msg_write.data_L = ntohl(msg_write.data_L);
|
msg_write.data_L = ntohl(msg_write.data_L);
|
err = DebugSetRegister(msg_write.address,msg_write.data_L);
|
err = DebugSetRegister(msg_write.address,msg_write.data_L);
|
resp_write.status = htonl(err);
|
resp_write.status = htonl(err);
|
if(gdb_write(&resp_write,sizeof(resp_write)) < 0)
|
if(gdb_write(&resp_write,sizeof(resp_write)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 4");
|
perror("gdb socket - 4");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
break;
|
break;
|
case JTAG_COMMAND_READ:
|
case JTAG_COMMAND_READ:
|
if(length != sizeof(msg_read) - 8)
|
if(length != sizeof(msg_read) - 8)
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
return;
|
return;
|
}
|
}
|
buf = (char*)&msg_read;
|
buf = (char*)&msg_read;
|
if(gdb_read(&buf[8],length) < 0)
|
if(gdb_read(&buf[8],length) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 5");
|
perror("gdb socket - 5");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
msg_read.address = ntohl(msg_read.address);
|
msg_read.address = ntohl(msg_read.address);
|
err = DebugGetRegister(msg_read.address,&resp_read.data_L);
|
err = DebugGetRegister(msg_read.address,&resp_read.data_L);
|
resp_read.status = htonl(err);
|
resp_read.status = htonl(err);
|
resp_read.data_H = 0;
|
resp_read.data_H = 0;
|
resp_read.data_L = htonl(resp_read.data_L);
|
resp_read.data_L = htonl(resp_read.data_L);
|
if(gdb_write(&resp_read,sizeof(resp_read)) < 0)
|
if(gdb_write(&resp_read,sizeof(resp_read)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 6");
|
perror("gdb socket - 6");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
break;
|
break;
|
case JTAG_COMMAND_BLOCK_WRITE:
|
case JTAG_COMMAND_BLOCK_WRITE:
|
if(length < sizeof(JTAGProxyBlockWriteMessage)-8)
|
if(length < sizeof(JTAGProxyBlockWriteMessage)-8)
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
return;
|
return;
|
}
|
}
|
if(!(buf = (char*)malloc(8+length)))
|
if(!(buf = (char*)malloc(8+length)))
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_OUT_OF_MEMORY);
|
ProtocolClean(length,JTAG_PROXY_OUT_OF_MEMORY);
|
return;
|
return;
|
}
|
}
|
msg_bwrite = (JTAGProxyBlockWriteMessage*)buf;
|
msg_bwrite = (JTAGProxyBlockWriteMessage*)buf;
|
if(gdb_read(&buf[8],length) < 0)
|
if(gdb_read(&buf[8],length) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 5");
|
perror("gdb socket - 5");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
free(buf);
|
free(buf);
|
return;
|
return;
|
}
|
}
|
msg_bwrite->address = ntohl(msg_bwrite->address);
|
msg_bwrite->address = ntohl(msg_bwrite->address);
|
msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters);
|
msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters);
|
for(i=0;i<msg_bwrite->nRegisters;i++)
|
for(i=0;i<msg_bwrite->nRegisters;i++)
|
{
|
{
|
int t_err = 0;
|
int t_err = 0;
|
|
|
msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]);
|
msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]);
|
t_err = DebugSetRegister(msg_bwrite->address + 4 * i,msg_bwrite->data[i]);
|
t_err = DebugSetRegister(msg_bwrite->address + 4 * i,msg_bwrite->data[i]);
|
err = err ? err : t_err;
|
err = err ? err : t_err;
|
}
|
}
|
resp_bwrite.status = htonl(err);
|
resp_bwrite.status = htonl(err);
|
free(buf);
|
free(buf);
|
buf = NULL;
|
buf = NULL;
|
msg_bwrite = NULL;
|
msg_bwrite = NULL;
|
if(gdb_write(&resp_bwrite,sizeof(resp_bwrite)) < 0)
|
if(gdb_write(&resp_bwrite,sizeof(resp_bwrite)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 4");
|
perror("gdb socket - 4");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
break;
|
break;
|
case JTAG_COMMAND_BLOCK_READ:
|
case JTAG_COMMAND_BLOCK_READ:
|
if(length != sizeof(msg_bread) - 8)
|
if(length != sizeof(msg_bread) - 8)
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
return;
|
return;
|
}
|
}
|
buf = (char*)&msg_bread;
|
buf = (char*)&msg_bread;
|
if(gdb_read(&buf[8],length) < 0)
|
if(gdb_read(&buf[8],length) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 5");
|
perror("gdb socket - 5");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
msg_bread.address = ntohl(msg_bread.address);
|
msg_bread.address = ntohl(msg_bread.address);
|
msg_bread.nRegisters = ntohl(msg_bread.nRegisters);
|
msg_bread.nRegisters = ntohl(msg_bread.nRegisters);
|
len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1);
|
len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1);
|
if(!(buf = (char*)malloc(len)))
|
if(!(buf = (char*)malloc(len)))
|
{
|
{
|
ProtocolClean(0,JTAG_PROXY_OUT_OF_MEMORY);
|
ProtocolClean(0,JTAG_PROXY_OUT_OF_MEMORY);
|
return;
|
return;
|
}
|
}
|
resp_bread = (JTAGProxyBlockReadResponse*)buf;
|
resp_bread = (JTAGProxyBlockReadResponse*)buf;
|
for(i=0;i<msg_bread.nRegisters;i++)
|
for(i=0;i<msg_bread.nRegisters;i++)
|
{
|
{
|
int t_err;
|
int t_err;
|
|
|
t_err = DebugGetRegister(msg_bread.address + 4 * i,&resp_bread->data[i]);
|
t_err = DebugGetRegister(msg_bread.address + 4 * i,&resp_bread->data[i]);
|
resp_bread->data[i] = htonl(resp_bread->data[i]);
|
resp_bread->data[i] = htonl(resp_bread->data[i]);
|
err = err ? err : t_err;
|
err = err ? err : t_err;
|
}
|
}
|
resp_bread->status = htonl(err);
|
resp_bread->status = htonl(err);
|
resp_bread->nRegisters = htonl(msg_bread.nRegisters);
|
resp_bread->nRegisters = htonl(msg_bread.nRegisters);
|
if(gdb_write(resp_bread,len) < 0)
|
if(gdb_write(resp_bread,len) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 6");
|
perror("gdb socket - 6");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
free(buf);
|
free(buf);
|
return;
|
return;
|
}
|
}
|
free(buf);
|
free(buf);
|
buf = NULL;
|
buf = NULL;
|
resp_bread = NULL;
|
resp_bread = NULL;
|
break;
|
break;
|
case JTAG_COMMAND_CHAIN:
|
case JTAG_COMMAND_CHAIN:
|
if(length != sizeof(msg_chain) - 8)
|
if(length != sizeof(msg_chain) - 8)
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
return;
|
return;
|
}
|
}
|
buf = (char*)&msg_chain;
|
buf = (char*)&msg_chain;
|
if(gdb_read(&buf[8],sizeof(msg_chain)-8) < 0)
|
if(gdb_read(&buf[8],sizeof(msg_chain)-8) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 7");
|
perror("gdb socket - 7");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
msg_chain.chain = htonl(msg_chain.chain);
|
msg_chain.chain = htonl(msg_chain.chain);
|
err = DebugSetChain(msg_chain.chain);
|
err = DebugSetChain(msg_chain.chain);
|
resp_chain.status = htonl(err);
|
resp_chain.status = htonl(err);
|
if(gdb_write(&resp_chain,sizeof(resp_chain)) < 0)
|
if(gdb_write(&resp_chain,sizeof(resp_chain)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 8");
|
perror("gdb socket - 8");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
break;
|
break;
|
default:
|
default:
|
ProtocolClean(length,JTAG_PROXY_COMMAND_NOT_IMPLEMENTED);
|
ProtocolClean(length,JTAG_PROXY_COMMAND_NOT_IMPLEMENTED);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
void ProtocolClean(int length,int32_t err)
|
void ProtocolClean(int length,int32_t err)
|
{
|
{
|
char buf[4096];
|
char buf[4096];
|
|
|
err = htonl(err);
|
err = htonl(err);
|
if((gdb_read(buf,length) < 0) ||
|
if((gdb_read(buf,length) < 0) ||
|
(gdb_write(&err,sizeof(err)) < 0) && gdb_fd)
|
(gdb_write(&err,sizeof(err)) < 0) && gdb_fd)
|
{
|
{
|
perror("gdb socket - 9");
|
perror("gdb socket - 9");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
}
|
}
|
|
|
static int gdb_write(const void* buf,int len)
|
static int gdb_write(const void* buf,int len)
|
{
|
{
|
int n, log_n = 0;
|
int n, log_n = 0;
|
const char* w_buf = (const char*)buf;
|
const char* w_buf = (const char*)buf;
|
const uint32_t* log_buf = (const uint32_t*)buf;
|
const uint32_t* log_buf = (const uint32_t*)buf;
|
struct pollfd block;
|
struct pollfd block;
|
|
|
while(len) {
|
while(len) {
|
if((n = write(gdb_fd,w_buf,len)) < 0) {
|
if((n = write(gdb_fd,w_buf,len)) < 0) {
|
switch(errno) {
|
switch(errno) {
|
case EWOULDBLOCK: /* or EAGAIN */
|
case EWOULDBLOCK: /* or EAGAIN */
|
/* We've been called on a descriptor marked
|
/* We've been called on a descriptor marked
|
for nonblocking I/O. We better simulate
|
for nonblocking I/O. We better simulate
|
blocking behavior. */
|
blocking behavior. */
|
block.fd = gdb_fd;
|
block.fd = gdb_fd;
|
block.events = POLLOUT;
|
block.events = POLLOUT;
|
block.revents = 0;
|
block.revents = 0;
|
poll(&block,1,-1);
|
poll(&block,1,-1);
|
continue;
|
continue;
|
case EINTR:
|
case EINTR:
|
continue;
|
continue;
|
case EPIPE:
|
case EPIPE:
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
return -1;
|
return -1;
|
default:
|
default:
|
return -1;
|
return -1;
|
}
|
}
|
}
|
}
|
else {
|
else {
|
len -= n;
|
len -= n;
|
w_buf += n;
|
w_buf += n;
|
if ( config.debug.vapi_id )
|
if ( config.debug.vapi_id )
|
for ( log_n += n; log_n >= 4; log_n -= 4, ++ log_buf )
|
for ( log_n += n; log_n >= 4; log_n -= 4, ++ log_buf )
|
vapi_write_log_file( VAPI_COMMAND_SEND, config.debug.vapi_id, ntohl(*log_buf) );
|
vapi_write_log_file( VAPI_COMMAND_SEND, config.debug.vapi_id, ntohl(*log_buf) );
|
}
|
}
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
static int gdb_read(void* buf,int len)
|
static int gdb_read(void* buf,int len)
|
{
|
{
|
int n, log_n = 0;
|
int n, log_n = 0;
|
char* r_buf = (char*)buf;
|
char* r_buf = (char*)buf;
|
uint32_t* log_buf = (uint32_t*)buf;
|
uint32_t* log_buf = (uint32_t*)buf;
|
struct pollfd block;
|
struct pollfd block;
|
|
|
while(len) {
|
while(len) {
|
if((n = read(gdb_fd,r_buf,len)) < 0) {
|
if((n = read(gdb_fd,r_buf,len)) < 0) {
|
switch(errno) {
|
switch(errno) {
|
case EWOULDBLOCK: /* or EAGAIN */
|
case EWOULDBLOCK: /* or EAGAIN */
|
/* We've been called on a descriptor marked
|
/* We've been called on a descriptor marked
|
for nonblocking I/O. We better simulate
|
for nonblocking I/O. We better simulate
|
blocking behavior. */
|
blocking behavior. */
|
block.fd = gdb_fd;
|
block.fd = gdb_fd;
|
block.events = POLLIN;
|
block.events = POLLIN;
|
block.revents = 0;
|
block.revents = 0;
|
poll(&block,1,-1);
|
poll(&block,1,-1);
|
continue;
|
continue;
|
case EINTR:
|
case EINTR:
|
continue;
|
continue;
|
default:
|
default:
|
return -1;
|
return -1;
|
}
|
}
|
}
|
}
|
else if(n == 0) {
|
else if(n == 0) {
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
return -1;
|
return -1;
|
}
|
}
|
else {
|
else {
|
len -= n;
|
len -= n;
|
r_buf += n;
|
r_buf += n;
|
if ( config.debug.vapi_id )
|
if ( config.debug.vapi_id )
|
for ( log_n += n; log_n >= 4; log_n -= 4, ++ log_buf )
|
for ( log_n += n; log_n >= 4; log_n -= 4, ++ log_buf )
|
vapi_write_log_file( VAPI_COMMAND_REQUEST, config.debug.vapi_id, ntohl(*log_buf) );
|
vapi_write_log_file( VAPI_COMMAND_REQUEST, config.debug.vapi_id, ntohl(*log_buf) );
|
}
|
}
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int gdbcomm_init ()
|
int gdbcomm_init ()
|
{
|
{
|
serverPort = config.debug.server_port;
|
serverPort = config.debug.server_port;
|
if(server_fd = GetServerSocket("or1ksim","tcp",serverPort))
|
if(server_fd = GetServerSocket("or1ksim","tcp",serverPort))
|
PRINTF("JTAG Proxy server started on port %d\n",serverPort);
|
PRINTF("JTAG Proxy server started on port %d\n",serverPort);
|
else
|
else
|
PRINTF("Cannot start JTAG proxy server on port %d\n", serverPort);
|
PRINTF("Cannot start JTAG proxy server on port %d\n", serverPort);
|
}
|
}
|
|
|