Line 2... |
Line 2... |
JTAG connects to or1k target ops. See or1k-tdep.c
|
JTAG connects to or1k target ops. See or1k-tdep.c
|
|
|
Copyright 1993-1995, 2000 Free Software Foundation, Inc.
|
Copyright 1993-1995, 2000 Free Software Foundation, Inc.
|
Contributed by Cygnus Support. Written by Marko Mlinar
|
Contributed by Cygnus Support. Written by Marko Mlinar
|
<markom@opencores.org>
|
<markom@opencores.org>
|
|
Areas noted by (CZ) were modified by Chris Ziomkowski
|
|
<chris@asics.ws>
|
|
|
This file is part of GDB.
|
This file is part of GDB.
|
|
|
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
|
Line 32... |
Line 34... |
#include "serial.h"
|
#include "serial.h"
|
#include "target.h"
|
#include "target.h"
|
#include "remote-utils.h"
|
#include "remote-utils.h"
|
#include "gdb_string.h"
|
#include "gdb_string.h"
|
#include "tm.h"
|
#include "tm.h"
|
|
/* Added by CZ 24/05/01 */
|
|
#include <sys/poll.h>
|
|
#include <sys/socket.h>
|
|
#include <netdb.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/tcp.h>
|
|
#include <sys/select.h>
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
|
#include <signal.h>
|
#include <signal.h>
|
#include <sys/types.h>
|
#include <sys/types.h>
|
#include <sys/stat.h>
|
#include <sys/stat.h>
|
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
Line 68... |
Line 79... |
|
|
/* Designates whether we are in SELECT_DR state, otherwise in
|
/* Designates whether we are in SELECT_DR state, otherwise in
|
RUN TEST/IDLE */
|
RUN TEST/IDLE */
|
static int select_dr = 0;
|
static int select_dr = 0;
|
|
|
/* Printer compatible device we have open. */
|
/* CZ - 24/05/01 - Changed to structure for remote/local */
|
static int lp;
|
typedef enum {
|
|
JTAG_NOT_CONNECTED = 0,
|
|
JTAG_LOCAL = 1,
|
|
JTAG_REMOTE = 2,
|
|
} jtag_location;
|
|
|
|
typedef struct {
|
|
union {
|
|
int lp; /* Printer compatible device we have open. */
|
|
int fd; /* Socket for remote or1k jtag interface */
|
|
} device;
|
|
jtag_location location;
|
|
} jtag_connection;
|
|
|
|
/* Our current connect information */
|
|
static jtag_connection connection;
|
|
|
/* Crc of current read or written data. */
|
/* Crc of current read or written data. */
|
static int crc_r, crc_w = 0;
|
static int crc_r, crc_w = 0;
|
|
|
/* Generates new crc, sending in new bit input_bit */
|
/* Generates new crc, sending in new bit input_bit */
|
Line 111... |
Line 137... |
|
|
static void
|
static void
|
jp1_reset_JTAG ()
|
jp1_reset_JTAG ()
|
{
|
{
|
unsigned char data;
|
unsigned char data;
|
|
int lp = connection.device.lp; /* CZ */
|
|
|
|
if(connection.location != JTAG_LOCAL)
|
|
error("jp1_reset_JTAG called without a local connection!");
|
|
|
data = 0;
|
data = 0;
|
write (lp, &data, sizeof (data));
|
write (lp, &data, sizeof (data));
|
JTAG_WAIT();
|
JTAG_WAIT();
|
data = TRST;
|
data = TRST;
|
write (lp, &data, sizeof (data));
|
write (lp, &data, sizeof (data));
|
Line 127... |
Line 158... |
static void
|
static void
|
jp1_write_JTAG (packet)
|
jp1_write_JTAG (packet)
|
unsigned char packet;
|
unsigned char packet;
|
{
|
{
|
unsigned char data;
|
unsigned char data;
|
|
int lp = connection.device.lp; /* CZ */
|
|
|
|
if(connection.location != JTAG_LOCAL)
|
|
error("jp1_write_JTAG called without a local connection!");
|
|
|
data = ((packet & 3) << 2) | TRST;
|
data = ((packet & 3) << 2) | TRST;
|
write (lp, &data, sizeof (data));
|
write (lp, &data, sizeof (data));
|
JTAG_WAIT();
|
JTAG_WAIT();
|
crc_w = crc_calc (crc_w, (packet >> 1)&1);
|
crc_w = crc_calc (crc_w, (packet >> 1)&1);
|
|
|
Line 144... |
Line 180... |
|
|
static int
|
static int
|
jp1_read_JTAG ()
|
jp1_read_JTAG ()
|
{
|
{
|
int data;
|
int data;
|
|
|
|
if(connection.location != JTAG_LOCAL) /* CZ */
|
|
error("jp1_read_JTAG called without a local connection!");
|
|
|
ioctl (data, 0x60b, &data);
|
ioctl (data, 0x60b, &data);
|
data = ((data & 0x80) != 0);
|
data = ((data & 0x80) != 0);
|
crc_r = crc_calc (crc_r, data);
|
crc_r = crc_calc (crc_r, data);
|
return data;
|
return data;
|
}
|
}
|
Line 210... |
Line 250... |
jp1_write_JTAG (1); /* SELECT_DR SCAN */
|
jp1_write_JTAG (1); /* SELECT_DR SCAN */
|
jp1_write_JTAG (1); /* SELECT_IR SCAN */
|
jp1_write_JTAG (1); /* SELECT_IR SCAN */
|
select_dr = 0;
|
select_dr = 0;
|
}
|
}
|
|
|
|
/* Added by CZ 24/05/01 */
|
|
static int jtag_proxy_write(int fd,void* buf,int len)
|
|
{
|
|
int n;
|
|
char* w_buf = (char*)buf;
|
|
struct pollfd block;
|
|
|
|
while(len)
|
|
{
|
|
if((n = write(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 = fd;
|
|
block.events = POLLOUT;
|
|
block.revents = 0;
|
|
poll(&block,1,-1);
|
|
continue;
|
|
case EINTR:
|
|
continue;
|
|
case EPIPE:
|
|
return JTAG_PROXY_SERVER_TERMINATED;
|
|
default:
|
|
return errno;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
len -= n;
|
|
w_buf += n;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Added by CZ 24/05/01 */
|
|
static int jtag_proxy_read(int fd,void* buf,int len)
|
|
{
|
|
int n;
|
|
char* r_buf = (char*)buf;
|
|
struct pollfd block;
|
|
|
|
while(len)
|
|
{
|
|
if((n = read(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 = fd;
|
|
block.events = POLLIN;
|
|
block.revents = 0;
|
|
poll(&block,1,-1);
|
|
continue;
|
|
case EINTR:
|
|
continue;
|
|
default:
|
|
return errno;
|
|
}
|
|
}
|
|
else if(n == 0)
|
|
return JTAG_PROXY_SERVER_TERMINATED;
|
|
else
|
|
{
|
|
len -= n;
|
|
r_buf += n;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int ReadResponse(int fd,void* buffer,int len)
|
|
{
|
|
int32_t status = 0;
|
|
int result = jtag_proxy_read(fd,&status,4);
|
|
char* buf = (char*)buffer;
|
|
|
|
status = ntohl(status);
|
|
*((int32_t*)buffer) = status;
|
|
|
|
if(result) return result;
|
|
if(status) return status;
|
|
|
|
result = jtag_proxy_read(fd,&buf[4],len-4);
|
|
return result;
|
|
}
|
|
|
|
/* Added by CZ 24/05/01 */
|
|
#ifndef ANSI_PROTOTYPES
|
|
static int jtag_send_proxy(va_alist)
|
|
va_dcl
|
|
#else
|
|
static int jtag_send_proxy(int command,...)
|
|
#endif
|
|
{
|
|
va_list ap;
|
|
int result = 0;
|
|
int fd = connection.device.fd;
|
|
JTAGProxyWriteMessage xmit_write;
|
|
JTAGProxyReadMessage xmit_read;
|
|
JTAGProxyChainMessage xmit_chain;
|
|
JTAGProxyWriteResponse recv_write;
|
|
JTAGProxyReadResponse recv_read;
|
|
JTAGProxyChainResponse recv_chain;
|
|
unsigned long long data,* ret_val;
|
|
uint32_t word1; /* Use word1 and word2 to ease portability to platforms */
|
|
uint32_t word2; /* without long long and for alignment reasons */
|
|
|
|
#ifndef ANSI_PROTOTYPES
|
|
int command;
|
|
|
|
va_start(ap);
|
|
command = va_arg(ap,int);
|
|
#else
|
|
va_start(ap, command);
|
|
#endif
|
|
|
|
|
|
|
|
if(connection.location == JTAG_REMOTE)
|
|
{
|
|
switch(command)
|
|
{
|
|
case JTAG_COMMAND_READ:
|
|
xmit_read.command = htonl(command);
|
|
xmit_read.length = htonl(sizeof(xmit_read)-8);
|
|
xmit_read.address = htonl(va_arg(ap,int));
|
|
ret_val = va_arg(ap,unsigned long long *);
|
|
/* intentional single equals */
|
|
if(result = jtag_proxy_write(fd,&xmit_read,sizeof(xmit_read)))
|
|
break;
|
|
if(result = ReadResponse(fd,&recv_read,sizeof(recv_read)))
|
|
break;
|
|
result = ntohl(recv_read.status);
|
|
word1 = ntohl(recv_read.data_H);
|
|
word2 = ntohl(recv_read.data_L);
|
|
*ret_val = (((unsigned long long)word1) << 32) | word2;
|
|
break;
|
|
case JTAG_COMMAND_WRITE:
|
|
xmit_write.command = htonl(command);
|
|
xmit_write.length = htonl(sizeof(xmit_write)-8);
|
|
xmit_write.address = htonl(va_arg(ap,int));
|
|
data = va_arg(ap,unsigned long long);
|
|
word1 = htonl(data >> 32);
|
|
word2 = htonl(data & 0xFFFFFFFF);
|
|
xmit_write.data_H = word1;
|
|
xmit_write.data_L = word2;
|
|
if(result = jtag_proxy_write(fd,&xmit_write,sizeof(xmit_write)))
|
|
break;
|
|
if(result = ReadResponse(fd,&recv_write,sizeof(recv_write)))
|
|
break;
|
|
result = recv_write.status;
|
|
break;
|
|
case JTAG_COMMAND_CHAIN:
|
|
xmit_chain.command = htonl(command);
|
|
xmit_chain.length = htonl(sizeof(xmit_chain)-8);
|
|
xmit_chain.chain = htonl(va_arg(ap,unsigned int));
|
|
if(result = jtag_proxy_write(fd,&xmit_chain,sizeof(xmit_chain)))
|
|
break;
|
|
if(result = ReadResponse(fd,&recv_chain,sizeof(recv_chain)))
|
|
break;
|
|
result = recv_chain.status;
|
|
break;
|
|
default:
|
|
result = JTAG_PROXY_INVALID_COMMAND;
|
|
break;
|
|
}
|
|
va_end(ap);
|
|
}
|
|
else
|
|
{
|
|
va_end(ap);
|
|
error("jtag_send_proxy called without a remote proxy connection!");
|
|
result = JTAG_PROXY_NO_CONNECTION;
|
|
}
|
|
|
|
if(result == JTAG_PROXY_SERVER_TERMINATED)
|
|
{
|
|
close(connection.device.fd);
|
|
connection.device.fd = 0;
|
|
connection.location = JTAG_NOT_CONNECTED;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Added by CZ 24/05/01 */
|
|
#ifndef ANSI_PROTOTYPES
|
|
static void jtag_proxy_error(va_alist)
|
|
va_dcl
|
|
#else
|
|
static void jtag_proxy_error(int result,int command,...)
|
|
#endif
|
|
{
|
|
va_list ap;
|
|
char sTemp[256];
|
|
|
|
#ifndef ANSI_PROTOTYPES
|
|
int result;
|
|
int command;
|
|
|
|
va_start(ap);
|
|
result = va_arg(ap,int);
|
|
command = va_arg(ap,int);
|
|
#else
|
|
va_start(ap, command);
|
|
#endif
|
|
|
|
switch(command)
|
|
{
|
|
case JTAG_COMMAND_READ:
|
|
sprintf(sTemp,"An error was reported by the proxy server. The command was:\n"
|
|
"\"JTAG_COMMAND_READ\",%u,0x%08x\nThe command returned %d.\n",
|
|
va_arg(ap,unsigned int),va_arg(ap,unsigned long long*),result);
|
|
error(sTemp);
|
|
break;
|
|
case JTAG_COMMAND_WRITE:
|
|
sprintf(sTemp,"An error was reported by the proxy server. The command was:\n"
|
|
"\"JTAG_COMMAND_WRITE\",%u,0x%016llx\nThe command returned %d.\n",
|
|
va_arg(ap,unsigned int),va_arg(ap,unsigned long long),result);
|
|
error(sTemp);
|
|
break;
|
|
case JTAG_COMMAND_CHAIN:
|
|
sprintf(sTemp,"An error was reported by the proxy server. The command was:\n"
|
|
"\"JTAG_COMMAND_CHAIN\",%u. The command returned %d.\n",
|
|
va_arg(ap,unsigned int));
|
|
error(sTemp);
|
|
break;
|
|
default:
|
|
sprintf(sTemp,"An error was reported by the proxy server. The command is "
|
|
"currently unimplemented.\nThe command code was %d, and the result "
|
|
"code was %d.\n",command,result);
|
|
error(sTemp);
|
|
break;
|
|
}
|
|
va_end(ap);
|
|
}
|
|
|
/* Sets register/memory regno to data. */
|
/* Sets register/memory regno to data. */
|
|
|
|
/* CZ 08/06/01: I am not sure how error checking is intended to
|
|
be implemented here. It appears that no indication is returned
|
|
to the caller as you have in standard unix system calls. Therefore,
|
|
I guess the only way to use these functions when you want to know
|
|
the exact position of the error is to manually clear err, call the
|
|
function, and then manually check err. I have also made some changes
|
|
where necessary because no value was returned at all int jtag_read_reg.
|
|
*/
|
|
|
void
|
void
|
jtag_write_reg (regno, data)
|
jtag_write_reg (regno, data)
|
int regno;
|
int regno;
|
ULONGEST data;
|
ULONGEST data;
|
{
|
{
|
int crc_read, crc_write, crc_ok, retry;
|
int crc_read, crc_write, crc_ok, retry;
|
|
int result;
|
|
|
|
switch(connection.location) /* CZ */
|
|
{
|
|
case JTAG_LOCAL:
|
if (!select_dr)
|
if (!select_dr)
|
jp1_write_JTAG (1); /* SELECT_DR SCAN */
|
jp1_write_JTAG (1); /* SELECT_DR SCAN */
|
select_dr = 1;
|
select_dr = 1;
|
|
|
/* If we don't have rw bit, we assume chain
|
/* If we don't have rw bit, we assume chain
|
Line 264... |
Line 562... |
JTAG_RETRY_WAIT();
|
JTAG_RETRY_WAIT();
|
}
|
}
|
else return;
|
else return;
|
}
|
}
|
err = ERR_CRC;
|
err = ERR_CRC;
|
|
break;
|
|
case JTAG_REMOTE:
|
|
if(result = jtag_send_proxy(JTAG_COMMAND_WRITE,regno,data))
|
|
{
|
|
jtag_proxy_error(result,JTAG_COMMAND_WRITE,regno,data);
|
|
err = result;
|
|
}
|
|
break;
|
|
default:
|
|
error("jtag_write_reg called with no connection!");
|
|
break;
|
|
}
|
}
|
}
|
|
|
/* Reads register/memory from regno. */
|
/* Reads register/memory from regno. */
|
|
|
ULONGEST
|
ULONGEST
|
jtag_read_reg (regno)
|
jtag_read_reg (regno)
|
unsigned int regno;
|
unsigned int regno;
|
{
|
{
|
ULONGEST data;
|
ULONGEST data;
|
int crc_read, crc_write, crc_actual_read, retry, crc_ok;
|
int crc_read, crc_write, crc_actual_read, retry, crc_ok;
|
|
int result;
|
|
|
|
switch(connection.location)
|
|
{
|
|
case JTAG_LOCAL:
|
if (!select_dr)
|
if (!select_dr)
|
jp1_write_JTAG (1); /* SELECT_DR SCAN */
|
jp1_write_JTAG (1); /* SELECT_DR SCAN */
|
select_dr = 1;
|
select_dr = 1;
|
|
|
for (retry = 0; retry < NUM_RETRIES; retry++)
|
for (retry = 0; retry < NUM_RETRIES; retry++)
|
Line 312... |
Line 626... |
crc_ok = jp1_read_JTAG ();
|
crc_ok = jp1_read_JTAG ();
|
jp1_write_JTAG (1); /* SELECT_DR */
|
jp1_write_JTAG (1); /* SELECT_DR */
|
if (chain_has_crc[current_chain])
|
if (chain_has_crc[current_chain])
|
{
|
{
|
if ((crc_read == crc_actual_read) && (crc_ok))
|
if ((crc_read == crc_actual_read) && (crc_ok))
|
return;
|
return -1; /* CZ */
|
JTAG_RETRY_WAIT();
|
JTAG_RETRY_WAIT();
|
}
|
}
|
else
|
else
|
return;
|
return -1; /* CZ */
|
}
|
}
|
err = ERR_CRC;
|
err = ERR_CRC;
|
|
break;
|
|
case JTAG_REMOTE:
|
|
if(result = jtag_send_proxy(JTAG_COMMAND_READ,regno,&data))
|
|
{
|
|
jtag_proxy_error(result,JTAG_COMMAND_READ,regno,&data);
|
|
err = result;
|
|
}
|
|
break;
|
|
default:
|
|
error("jtag_write_reg called with no connection!");
|
|
break;
|
|
}
|
|
|
|
return data; /* CZ */
|
}
|
}
|
|
|
/* Sets scan chain. */
|
/* Sets scan chain. */
|
|
|
void
|
void
|
jtag_set_chain (chain)
|
jtag_set_chain (chain)
|
int chain;
|
int chain;
|
{
|
{
|
|
int result;
|
|
|
|
switch(connection.location)
|
|
{
|
|
case JTAG_LOCAL:
|
if (current_chain != chain)
|
if (current_chain != chain)
|
{
|
{
|
if (!chain_is_valid[chain])
|
if (!chain_is_valid[chain])
|
error ("Chain not valid.");
|
error ("Chain not valid.");
|
|
|
Line 365... |
Line 698... |
|
|
jp1_write_JTAG (1); /* UPDATE_IR */
|
jp1_write_JTAG (1); /* UPDATE_IR */
|
jp1_write_JTAG (1); /* SELECT_DR */
|
jp1_write_JTAG (1); /* SELECT_DR */
|
select_dr = 1;
|
select_dr = 1;
|
}
|
}
|
|
break;
|
|
case JTAG_REMOTE:
|
|
if(current_chain != chain)
|
|
{
|
|
if(result = jtag_send_proxy(JTAG_COMMAND_CHAIN,chain))
|
|
{
|
|
jtag_proxy_error(result,JTAG_COMMAND_CHAIN,chain);
|
|
err = result;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
error("jtag_set_chain called with no connection!");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Added by CZ 24/05/01 */
|
|
static int jtag_connect_to_server(char* hostname,char* name)
|
|
{
|
|
struct hostent *host;
|
|
struct sockaddr_in sin;
|
|
struct servent *service;
|
|
struct protoent *protocol;
|
|
int sock,flags;
|
|
int fd;
|
|
char sTemp[256],sTemp2[256];
|
|
char* proto_name = "tcp";
|
|
int port = 0;
|
|
int on_off = 0; /* Turn off Nagel's algorithm on the socket */
|
|
char *s;
|
|
|
|
if(!(protocol = getprotobyname(proto_name)))
|
|
{
|
|
sprintf(sTemp,"jtag_connect_to_server: Protocol \"%s\" not available.\n",
|
|
proto_name);
|
|
error(sTemp);
|
|
return 0;
|
|
}
|
|
|
|
/* Convert name to an integer only if it is well formatted.
|
|
Otherwise, assume that it is a service name. */
|
|
|
|
port = strtol(name,&s,10);
|
|
if(*s)
|
|
port = 0;
|
|
|
|
if(!port)
|
|
{
|
|
if(!(service = getservbyname(name,protocol->p_name)))
|
|
{
|
|
sprintf(sTemp,"jtag_connect_to_server: Unknown service \"%s\".\n",name);
|
|
error(sTemp);
|
|
return 0;
|
|
}
|
|
|
|
port = ntohs(service->s_port);
|
|
}
|
|
|
|
if(!(host = gethostbyname(hostname)))
|
|
{
|
|
sprintf(sTemp,"jtag_connect_to_server: Unknown host \"%s\"\n",hostname);
|
|
error(sTemp);
|
|
return 0;
|
|
}
|
|
|
|
if((sock = socket(PF_INET,SOCK_STREAM,0)) < 0)
|
|
{
|
|
sprintf(sTemp,"jtag_connect_to_server: can't create socket errno = %d\n",
|
|
errno);
|
|
sprintf(sTemp2,"%s\n",strerror(errno));
|
|
strcat(sTemp,sTemp2);
|
|
error(sTemp);
|
|
return 0;
|
|
}
|
|
|
|
if(fcntl(sock,F_GETFL,&flags) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to get flags for JTAG proxy socket %d",sock);
|
|
error(sTemp);
|
|
close(sock);
|
|
return 0;
|
|
}
|
|
|
|
if(fcntl(sock,F_SETFL, flags & ~O_NONBLOCK) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to set flags for JTAG proxy socket %d to value 0x%08x",
|
|
sock,flags | O_NONBLOCK);
|
|
error(sTemp);
|
|
close(sock);
|
|
return 0;
|
|
}
|
|
|
|
memset(&sin,0,sizeof(sin));
|
|
sin.sin_family = host->h_addrtype;
|
|
memcpy(&sin.sin_addr,host->h_addr_list[0],host->h_length);
|
|
sin.sin_port = htons(port);
|
|
|
|
if((connect(sock,(struct sockaddr*)&sin, sizeof(sin)) < 0)
|
|
&& errno != EINPROGRESS)
|
|
{
|
|
|
|
sprintf(sTemp,"jtag_connect_to_server: connect failed errno = %d\n",errno);
|
|
sprintf(sTemp2,"%s\n",strerror(errno));
|
|
close(sock);
|
|
strcat(sTemp,sTemp2);
|
|
error(sTemp);
|
|
return 0;
|
|
}
|
|
|
|
if(fcntl(sock,F_SETFL, flags | O_NONBLOCK) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to set flags for JTAG proxy socket %d to value 0x%08x",
|
|
sock,flags | O_NONBLOCK);
|
|
error(sTemp);
|
|
close(sock);
|
|
return 0;
|
|
}
|
|
|
|
if(setsockopt(sock,protocol->p_proto,TCP_NODELAY,&on_off,sizeof(int)) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",sock);
|
|
error(sTemp);
|
|
close(sock);
|
|
return 0;
|
|
}
|
|
|
|
return sock;
|
}
|
}
|
|
|
/* Initialize a new connection to the or1k board, and make sure we are
|
/* Initialize a new connection to the or1k board, and make sure we are
|
really connected. */
|
really connected. */
|
|
|
Line 378... |
Line 839... |
{
|
{
|
char *ptype;
|
char *ptype;
|
char *port_name;
|
char *port_name;
|
char **argv;
|
char **argv;
|
|
|
if (args == 0)
|
if (args == 0) /* CZ */
|
error ("To open a or1k remote debugging connection, you need to specify what parallel\n"
|
error ( "To open a or1k remote debugging connection, you need to specify a "
|
"port device is attached to the target board (e.g., /dev/lp0).\n");
|
"parallel port\nconnected to the target board, or else a remote "
|
|
"server which will proxy these\nservices for you.\nExample: "
|
|
"/dev/lp0 or jtag://debughost.mydomain.com:8100.\n");
|
|
|
|
/* If we currently have an open connection, shut it
|
|
down. This is due to a temporary bug in gdb. */
|
|
switch(connection.location)
|
|
{
|
|
case JTAG_REMOTE:
|
|
if(connection.device.fd > 0)
|
|
{
|
|
close(connection.device.fd);
|
|
}
|
|
break;
|
|
case JTAG_LOCAL:
|
|
if(connection.device.lp > 0)
|
|
{
|
|
close(connection.device.lp);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
/* Parse the port name. */
|
/* Parse the port name. */
|
if ((argv = buildargv (args)) == NULL)
|
if ((argv = buildargv (args)) == NULL)
|
nomem (0);
|
nomem (0);
|
port_name = strsave (argv[0]);
|
port_name = strsave (argv[0]);
|
make_cleanup_freeargv (argv);
|
make_cleanup_freeargv (argv);
|
|
|
|
/* CZ 24/05/01 - Check to see if we have specified a remote
|
|
jtag interface or a local one. It is remote if it follows
|
|
the URL naming convention jtag://<hostname>:<port> */
|
|
if(!strncmp(port_name,"jtag://",7))
|
|
{
|
|
char *port = strchr(&port_name[7],':');
|
|
char hostname[256];
|
|
|
|
if(port)
|
|
{
|
|
int len = port - port_name - 7;
|
|
strncpy(hostname,&port_name[7],len);
|
|
hostname[len] = '\0';
|
|
port++;
|
|
}
|
|
else
|
|
strcpy(hostname,&port_name[7]);
|
|
|
|
/* Interface is remote */
|
|
if(!(connection.device.fd = jtag_connect_to_server(hostname,port)))
|
|
{
|
|
char sTemp[256];
|
|
sprintf(sTemp,"Can not access JTAG Proxy Server at \"%s\"",
|
|
&port_name[5]);
|
|
error(sTemp);
|
|
}
|
|
connection.location = JTAG_REMOTE;
|
|
printf_unfiltered ("Remote or1k debugging using %s\n",port_name);
|
|
}
|
|
else
|
|
{
|
|
/* Interface is local */
|
/* Open and initialize the parallel port. */
|
/* Open and initialize the parallel port. */
|
lp = open (port_name, O_WRONLY);
|
connection.device.lp = open (port_name, O_WRONLY);
|
if (lp < 0)
|
if (connection.device.lp < 0)
|
error ("Cannot open device.");
|
error ("Cannot open device.");
|
|
connection.location = JTAG_LOCAL; /* CZ */
|
|
printf_unfiltered ("Local or1k debugging using %s\n", port_name);
|
|
|
printf_unfiltered ("Remote or1k debugging using %s\n", port_name);
|
}
|
|
|
current_chain = -1;
|
current_chain = -1;
|
|
if(connection.location == JTAG_LOCAL)
|
jp1_reset_JTAG ();
|
jp1_reset_JTAG ();
|
jtag_set_chain (SC_RISC_DEBUG);
|
jtag_set_chain (SC_RISC_DEBUG);
|
|
|
free (port_name);
|
free (port_name);
|
}
|
}
|
|
|
void
|
void
|
jtag_done ()
|
jtag_done () /* CZ */
|
|
{
|
|
switch(connection.location)
|
{
|
{
|
close (lp);
|
case JTAG_LOCAL:
|
|
sync_close (connection.device.lp);
|
|
connection.device.lp = 0;
|
|
break;
|
|
case JTAG_REMOTE:
|
|
sync_close(connection.device.fd);
|
|
connection.device.fd = 0;
|
|
break;
|
|
default:
|
|
error("No jtag connection specified!");
|
|
break;
|
|
}
|
|
connection.location = JTAG_NOT_CONNECTED;
|
|
}
|
|
|
|
int sync_close(int fd)
|
|
{
|
|
int flags = 0;
|
|
struct linger linger;
|
|
char sTemp[256];
|
|
|
|
linger.l_onoff = 0;
|
|
linger.l_linger = 0;
|
|
|
|
/* First, make sure we're non blocking */
|
|
if(fcntl(fd,F_GETFL,&flags) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to get flags for JTAG proxy socket %d",fd);
|
|
error(sTemp);
|
|
}
|
|
if(fcntl(fd,F_SETFL, flags & ~O_NONBLOCK) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to set flags for JTAG proxy socket %d to value 0x%08x",
|
|
fd,flags | O_NONBLOCK);
|
|
error(sTemp);
|
|
}
|
|
|
|
/* Now, make sure we don't linger around */
|
|
if(setsockopt(fd,SOL_SOCKET,SO_LINGER,&linger,sizeof(linger)) < 0)
|
|
{
|
|
sprintf(sTemp,"Unable to disable SO_LINGER for JTAG proxy socket %d.",fd);
|
|
error(sTemp);
|
|
}
|
|
|
|
return close(fd);
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|