URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [gdb-5.3/] [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 (ULONGEST) 0; 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,%p\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), result); 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 int),va_arg(ap,unsigned int),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 int),va_arg(ap,unsigned int),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 ((ULONGEST)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 = (int)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 ((ULONGEST)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 = (int)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_read_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, (ULONGEST)*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_block 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_read_block 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 ((ULONGEST)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 ((ULONGEST)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 ((ULONGEST)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; 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); 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 really connected. */ void jtag_init (args) char * args; { 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); } static int sync_close(int fd); 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); }