OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [jtag.c] - Rev 1765

Compare with Previous | Blame | View Log

/* Remote debugging interface for JTAG debugging protocol.
   JTAG connects to or1k target ops. See or1k-tdep.c
 
   Copyright 1993-1995, 2000 Free Software Foundation, Inc.
   Contributed by Cygnus Support.  Written by Marko Mlinar
   <markom@opencores.org>
   Areas noted by (CZ) were modified by Chris Ziomkowski
   <chris@asics.ws>
 
   This file is part of GDB.
 
   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
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
 
#include "defs.h"
#include "inferior.h"
#include "bfd.h"
#include "symfile.h"
#include "gdb_wait.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "serial.h"
#include "target.h"
#include "remote-utils.h"
#include "gdb_string.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 <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
 
#define TCLK (0x01)
#define TRST (0x02)
#define JTAG_WAIT()
#define NUM_RETRIES (16)
#define JTAG_RETRY_WAIT() usleep (100)
 
/* Selects crc trailer size in bits. Currently supported: 8 */
#define CRC_SIZE (8)
 
/* Scan chain size in bits.  */
#define SC_SIZE (4)
 
/* Scan chain info. */
/* *INDENT-OFF* */
static int chain_addr_size[] = { 0,  32, 0,  0,  5  };
static int chain_data_size[] = { 0,  32, 0,  32, 32 };
static int chain_is_valid[]  = { 0,  1,  0,  1,  1  };
static int chain_has_crc[]   = { 0,  1,  0,  1,  1  };
static int chain_has_rw[]    = { 0,  1,  0,  0,  1  };
/* *INDENT-OFF* */
 
/* Currently selected scan chain - just to prevent unnecessary
   transfers. */
static int current_chain;
 
/* Designates whether we are in SELECT_DR state, otherwise in
   RUN TEST/IDLE */
static int select_dr = 0;
 
/* CZ - 24/05/01 - Changed to structure for remote/local */
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.  */
static int crc_r, crc_w = 0;
 
/* Generates new crc, sending in new bit input_bit */
 
static int
crc_calc (int crc, int input_bit)
{
  int c;
  int new_crc;
  int d;
 
#if (CRC_SIZE == 8)
  d = input_bit&1;
  c = crc;
 
  /* Move queue left.  */
  new_crc = crc << 1;
 
  /* Mask upper five bits.  */
  new_crc &= 0xF8;
 
  /* Set lower three bits */
  new_crc |= (d ^ ((c >> 7)&1));
  new_crc |= (d ^ ((c >> 0)&1) ^ ((c >> 7)&1)) << 1;
  new_crc |= (d ^ ((c >> 1)&1) ^ ((c >> 7)&1)) << 2;
  return new_crc;
#else
  return 0;
#endif
}
 
/* Resets JTAG.
   Writes TRST=0
   and    TRST=1 */
 
static void
jp1_reset_JTAG ()
{
  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;
  write (lp, &data, sizeof (data));
  JTAG_WAIT();
  data = TRST;
  write (lp, &data, sizeof (data));
  JTAG_WAIT();
}
 
/* Writes TCLK=0, TRST=1, TMS=bit0, TDI=bit1
   and    TCLK=1, TRST=1, TMS=bit0, TDI=bit1 */
 
static void
jp1_write_JTAG (packet)
     unsigned char packet;
{
  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;
  write (lp, &data, sizeof (data));
  JTAG_WAIT();
  crc_w = crc_calc (crc_w, (packet >> 1)&1);
 
  /* rise clock */
  data |= TCLK;
  write (lp, &data, sizeof (data)); 
  JTAG_WAIT();
}
 
/* Reads TDO, using IOCTL.  */
 
static int
jp1_read_JTAG ()
{
  int data;
 
  if(connection.location != JTAG_LOCAL)    /* CZ */
    error("jp1_read_JTAG called without a local connection!");
 
  ioctl (data, 0x60b, &data);
  data = ((data & 0x80) != 0);
  crc_r = crc_calc (crc_r, data);
  return data;
}
 
/* Writes bitstream.  MS bit first.  */
 
static void
jp1_write_stream (stream, len, set_last_bit)
     ULONGEST stream;
     int len;
     int set_last_bit;
{
  int i;
  if (len <= 0) return; 
  for (i = len - 1; i > 0; i--)
    jp1_write_JTAG (((stream >> i) & 1) << 1);
 
  if (set_last_bit)
    jp1_write_JTAG (((stream & 1) << 1) | 1);
  else
    jp1_write_JTAG ((stream & 1) << 1);
}
 
/* Gets bitstream.  MS bit first.  */
 
static ULONGEST
jp1_read_stream (len, stream, set_last_bit)
     int len;
     unsigned long stream;
     int set_last_bit;
{
  int i;
  ULONGEST data;
 
  if (len <= 0) return; 
  data = 0;
  for (i = 0; i < len-1; i++)
    {      
      jp1_write_JTAG (0 + ((stream & 1) << 1));
      stream >>= 1;
      data <<= 1;
      data |= jp1_read_JTAG ();
    }
 
  if (set_last_bit)
    jp1_write_JTAG (1 + (stream & 1) << 1);
  else
    jp1_write_JTAG (0 + (stream & 1) << 1);
  data <<= 1;
  data |= jp1_read_JTAG ();
  return data;
}
 
/* Goes into SELECT_IR state. Should be called before every control write.  */
 
static void
jp1_prepare_control ()
{
  if (!select_dr)
    jp1_write_JTAG (1); /* SELECT_DR SCAN */
  jp1_write_JTAG (1);   /* SELECT_IR SCAN */
  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;
  char* buf = (char*)buffer;
 
	result = jtag_proxy_read(fd,&status,4);
 
  status = ntohl(status);
  *((int32_t*)buffer) = status;
 
  if(result)    {printf("result %i %x\n", result, result); return result;}
  if(status)    {printf("status %i %x\n", status, 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;
  JTAGProxyBlockWriteMessage *xmit_bwrite;
  JTAGProxyBlockReadMessage xmit_bread;
  JTAGProxyWriteResponse recv_write;
  JTAGProxyReadResponse recv_read;
  JTAGProxyChainResponse recv_chain;
  JTAGProxyBlockWriteResponse recv_bwrite;
  JTAGProxyBlockReadResponse recv_bread;
  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 */
  unsigned long  address;
  unsigned long* b_data; 
  int nRegisters;
  int len,i;
 
#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_BLOCK_WRITE:
	  address = va_arg(ap,unsigned long);
	  b_data = va_arg(ap,unsigned long*);
	  nRegisters = va_arg(ap,int);
	  len = sizeof(JTAGProxyBlockWriteMessage) + (nRegisters-1)*4;
	  xmit_bwrite = (JTAGProxyBlockWriteMessage*)malloc(len);
	  xmit_bwrite->command = htonl(command);
	  xmit_bwrite->length = htonl(len-8);
	  xmit_bwrite->address = htonl(address);
	  xmit_bwrite->nRegisters = htonl(nRegisters);
	  for(i=0;i<nRegisters;i++)
	    xmit_bwrite->data[i] = htonl(b_data[i]);
	  if(!(result = jtag_proxy_write(fd,xmit_bwrite,len)) &&
	     !(result = ReadResponse(fd,&recv_bwrite,sizeof(recv_bwrite))))
	    result = recv_bwrite.status;
	  free(xmit_bwrite);
	  xmit_bwrite = NULL;
	  break;
	case JTAG_COMMAND_BLOCK_READ:
	  address = va_arg(ap,unsigned long);
	  b_data = va_arg(ap,unsigned long*);
	  nRegisters = va_arg(ap,int);
	  xmit_bread.command = htonl(command);
	  xmit_bread.length = htonl(sizeof(xmit_bread)-8);
	  xmit_bread.address = htonl(address);
	  xmit_bread.nRegisters = htonl(nRegisters);
	  if(result = jtag_proxy_write(fd,&xmit_bread,sizeof(xmit_bread)))
	    break;
	  if(result = ReadResponse(fd,&recv_bread,sizeof(recv_bread)))
	    break;
	  b_data[0] = ntohl(recv_bread.data[0]);
	  recv_bread.nRegisters = ntohl(recv_bread.nRegisters);
	  if(result = jtag_proxy_read(fd,&b_data[1],4*(recv_bread.nRegisters-1)))
	    break;
	  if(recv_bread.nRegisters != nRegisters)
	    result = JTAG_PROXY_PROTOCOL_ERROR;
	  else
	    {
	      for(i=1;i<nRegisters;i++)
		b_data[i] = ntohl(b_data[i]);
	    }
	  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;
    case JTAG_COMMAND_BLOCK_READ:
      sprintf(sTemp,"An error was reported by the proxy server. The command was:\n"
	      "\"JTAG_COMMAND_BLOCK_READ\",0x%08x,0x%08x,%d\nThe command returned %d.\n",
	      va_arg(ap,unsigned long),va_arg(ap,unsigned long),va_arg(ap,int),result);
      error(sTemp);
      break;
    case JTAG_COMMAND_BLOCK_WRITE:
    default:
      sprintf(sTemp,"An error was reported by the proxy server. The command was:\n"
	      "\"JTAG_COMMAND_BLOCK_WRITE\",0x%08x,0x%08x,%d\nThe command returned %d.\n",
	      va_arg(ap,unsigned long),va_arg(ap,unsigned long),va_arg(ap,int),result);
      error(sTemp);
      break;
    }
  va_end(ap);
}
 
/* 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
jtag_write_reg (regno, data)
     int regno;
     ULONGEST data;
{
  int crc_read, crc_write, crc_ok, retry;
  int result;
 
#ifdef DEBUG_JTAG
  printf_unfiltered ("write reg %x <- %x\n", regno, data);
  fflush (stdout);
#endif
  switch(connection.location) /* CZ */
    {
    case JTAG_LOCAL:
      if (!select_dr)
	jp1_write_JTAG (1); /* SELECT_DR SCAN */
      select_dr = 1;
 
      /* If we don't have rw bit, we assume chain
	 is read only. */
      if (!chain_has_rw[current_chain])
	error ("Internal: Chain not writable.");
 
      for (retry = 0; retry < NUM_RETRIES; retry++)
	{
	  jp1_write_JTAG (0); /* CAPTURE_DR */
	  jp1_write_JTAG (0); /* SHIFT_DR */
	  crc_w = 0;
 
	  /* write addr */
	  jp1_write_stream (regno, chain_addr_size[current_chain], 0);
 
	  /* write (R/W=1) - we tested that previously. */
	  jp1_write_JTAG (2);
 
	  /* write data */
	  jp1_write_stream (data, chain_data_size[current_chain], 0); 
	  if (chain_has_crc[current_chain])
	    {
	      crc_write = crc_w;
 
	      /* write CRC, EXIT1_DR */
	      crc_read = jp1_read_stream (crc_write, CRC_SIZE, 1);
	    }
	  jp1_write_JTAG (1); /* UPDATE_DR */
 
	  /* Did JTAG receive packet correctly? */
	  if (chain_has_crc[current_chain])
	    crc_ok = jp1_read_JTAG ();
	  jp1_write_JTAG (1); /* SELECT_DR */
	  if (chain_has_crc[current_chain])
	    {
	      if ((crc_read == crc_write) && (crc_ok))
		return;
	      JTAG_RETRY_WAIT();
	    }
	  else return;
	}
      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;
    }
#ifdef DEBUG_JTAG
  printf_unfiltered ("!write reg\n");
  fflush (stdout);
#endif
}
 
/* Reads register/memory from regno.  */
 
ULONGEST
jtag_read_reg (regno)
     unsigned int regno;
{
  ULONGEST data;
  int crc_read, crc_write, crc_actual_read,  retry, crc_ok;
  int result;
 
#ifdef DEBUG_JTAG
  printf_unfiltered ("read reg %x\n", regno);
  fflush (stdout);
#endif
  switch(connection.location)
    {
    case JTAG_LOCAL:
      if (!select_dr)
	jp1_write_JTAG (1); /* SELECT_DR SCAN */
      select_dr = 1;
 
      for (retry = 0; retry < NUM_RETRIES; retry++)
	{      
	  jp1_write_JTAG (0); /* CAPTURE_DR */
	  jp1_write_JTAG (0); /* SHIFT_DR */
	  crc_w = 0;
 
	  /* write addr */
	  jp1_write_stream (regno, chain_addr_size[current_chain], 0);
 
	  /* read (R/W=0) */
	  if (chain_has_rw[current_chain])
	    jp1_write_JTAG (0);
	  if (chain_has_crc[current_chain])
	    {
	      crc_r = 0;
 
	      /* data = 0 */
	      data = jp1_read_stream (0, chain_data_size[current_chain], 0);
	      crc_write = crc_w;
	      crc_actual_read = crc_read;
 
	      /* Send my crc, EXIT1_DR */
	      crc_read = jp1_read_stream (crc_write, CRC_SIZE, 1);
	    }
	  jp1_write_JTAG (1); /* UPDATE_DR */
 
	  /* Did JTAG receive packet correctly? */
	  if (chain_has_crc[current_chain])
	    crc_ok = jp1_read_JTAG ();
	  jp1_write_JTAG (1); /* SELECT_DR */
	  if (chain_has_crc[current_chain])
	    {
	      if ((crc_read == crc_actual_read) && (crc_ok))
		return -1;  /* CZ */
	      JTAG_RETRY_WAIT();
	    }
	  else
	    return -1;  /* CZ */
	}
      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;
    }
 
#ifdef DEBUG_JTAG
  printf_unfiltered ("read reg %x\n", data);
  fflush (stdout);
#endif
  return data;  /* CZ */
}
 
int jtag_write_block(unsigned int regno,void* data,int nRegisters)
{
  unsigned long* buffer = (unsigned long*)data;
  int i,result;
 
  if(nRegisters == 1) {
    jtag_write_reg(regno, *buffer);
    return err;
  }
 
#ifdef DEBUG_JTAG
  printf_unfiltered ("write block %x,%i\n", regno, nRegisters);
  fflush (stdout);
#endif
 
  err = 0;
  switch(connection.location)
    {
    case JTAG_LOCAL:         /* We can't do any better than this locally */
      for(i=0;i<nRegisters;i++)
	jtag_write_reg(regno+i,(ULONGEST)buffer[i]);
      break;
    case JTAG_REMOTE:
      if(result = jtag_send_proxy(JTAG_COMMAND_BLOCK_WRITE,regno,data,nRegisters))
	{
	  jtag_proxy_error(result,JTAG_COMMAND_BLOCK_WRITE,regno,data,nRegisters);
	  err = result;
	}
      break;
    default:
      error("jtag_write_reg called with no connection!");
      break;
    }
 
#ifdef DEBUG_JTAG
  printf_unfiltered ("!write block\n");
  fflush (stdout);
#endif
  return err;
}
 
int jtag_read_block(unsigned int regno,void* data,int nRegisters)
{
  unsigned long* buffer = (unsigned long*)data;
  int i,result;
 
#ifdef DEBUG_JTAG
  printf_unfiltered ("read block %x,%i\n", regno, nRegisters);
  fflush (stdout);
#endif
 
  /*  if(nRegisters == 1) {
    *buffer = jtag_read_reg(regno);
    return err;
    }*/
  err = 0;
  switch(connection.location)
    {
    case JTAG_LOCAL:         /* We can't do any better than this locally */
      for(i=0;i<nRegisters;i++)
	buffer[i] = (unsigned long)jtag_read_reg(regno+i);
      break;
    case JTAG_REMOTE:
      if(result = jtag_send_proxy(JTAG_COMMAND_BLOCK_READ,regno,data,nRegisters))
	{
	  jtag_proxy_error(result,JTAG_COMMAND_BLOCK_READ,regno,data,nRegisters);
	  err = result;
	}
      break;
    default:
      error("jtag_write_reg called with no connection!");
      break;
    }
 
#ifdef DEBUG_JTAG
  printf_unfiltered ("read block\n");
  fflush (stdout);
#endif  
  return err;
}
 
/* Sets scan chain.  */
 
void
jtag_set_chain (chain)
     int chain;
{
  int result;
 
#ifdef DEBUG_JTAG
  printf_unfiltered ("set chain %x\n", chain);
  fflush (stdout);
#endif
  switch(connection.location)
    {
    case JTAG_LOCAL:
      if (current_chain != chain)
	{
	  if (!chain_is_valid[chain])
	    error ("Chain not valid.");
 
	  current_chain = chain;
	  jp1_prepare_control ();
 
	  jp1_write_JTAG (0); /* CAPTURE_IR */
	  jp1_write_JTAG (0); /* SHIFT_IR */
 
	  /* write data, EXIT1_IR */
	  jp1_write_stream (JI_CHAIN_SELECT, JI_SIZE, 4);
 
	  jp1_write_JTAG (1); /* UPDATE_IR */
	  jp1_write_JTAG (1); /* SELECT_DR */
 
	  jp1_write_JTAG (0); /* CAPTURE_DR */
	  jp1_write_JTAG (0); /* SHIFT_DR */
 
	  /* write data, EXIT1_DR */
	  jp1_write_stream (chain, SC_SIZE, 1);
 
	  jp1_write_JTAG (1); /* UPDATE_DR */
	  jp1_write_JTAG (1); /* SELECT_DR */
 
	  /* Now we have to go out of SELECT_CHAIN mode.  */
	  jp1_write_JTAG (1); /* SELECT_IR */
	  jp1_write_JTAG (0); /* CAPTURE_IR */
	  jp1_write_JTAG (0); /* SHIFT_IR */
 
	  /* write data, EXIT1_IR */
	  jp1_write_stream (JI_DEBUG, JI_SIZE,1 );
 
	  jp1_write_JTAG (1); /* UPDATE_IR */
	  jp1_write_JTAG (1); /* SELECT_DR */
	  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;
    }
#ifdef DEBUG_JTAG
  printf_unfiltered ("!set chain\n");
  fflush (stdout);
#endif
}
 
/* 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(flags = fcntl(sock,F_GETFL,0) < 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);
      perror("fcntl ~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);
      perror("fcntl | 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
   really connected.  */
 
void
jtag_init (args)
     char * args;
{
  char *ptype;
  char *port_name;
  char **argv;
 
#ifdef DEBUG_JTAG
  printf_unfiltered ("INIT\n");
  fflush(stdout);
#endif
  if (args == 0) /* CZ */
    error ( "To open a or1k remote debugging connection, you need to specify a "
	    "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.  */
  if ((argv = buildargv (args)) == NULL)
    nomem (0);
  port_name = xstrdup (argv[0]);
  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.  */
      connection.device.lp = open (port_name, O_WRONLY);
      if (connection.device.lp < 0)
	error ("Cannot open device.");
      connection.location = JTAG_LOCAL; /* CZ */
      printf_unfiltered ("Local or1k debugging using %s\n", port_name);
 
    }
 
  current_chain = -1;
  if(connection.location == JTAG_LOCAL)
    jp1_reset_JTAG ();
  jtag_set_chain (SC_RISC_DEBUG);
 
  free (port_name);
}
 
void
jtag_done ()  /* CZ */
{
  switch(connection.location)
    {
    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:
      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(flags = fcntl(fd,F_GETFL,0) < 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);
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.