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

Subversion Repositories or1k_old

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k_old/trunk/rc203soc/sw/jtag
    from Rev 1765 to Rev 1782
    Reverse comparison

Rev 1765 → Rev 1782

/gdb2.c
0,0 → 1,583
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
 
/* Libraries for JTAG proxy server. */
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <inttypes.h>
#include <errno.h>
 
#include "gdb.h" /* partially copied from gdb/config/or1k */
#include "jp.h" /* just for debug() */
#include "jp2.h"
 
 
/* connection to jp2 routines */
int gdb_chain = -1;
 
int gdb_read_reg(unsigned long adr, unsigned long *data) {
debug("rr %d\n", gdb_chain);
switch (gdb_chain) {
case SC_RISC_DEBUG: return dbg_cpu0_read(adr, data) ? ERR_CRC : ERR_NONE;
case SC_REGISTER: return dbg_cpu0_read_ctrl(adr, (unsigned char*)data) ? ERR_CRC : ERR_NONE;
case SC_WISHBONE: return dbg_wb_read32(adr, data) ? ERR_CRC : ERR_NONE;
case SC_TRACE: *data = 0; return 0;
default: return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_write_reg(unsigned long adr, unsigned long data) {
debug("wr %d\n", gdb_chain);
switch (gdb_chain) { /* remap registers, to be compatible with jp1 */
case SC_RISC_DEBUG: if (adr == JTAG_RISCOP) adr = 0x00;
return dbg_cpu0_write(adr, data) ? ERR_CRC : ERR_NONE;
case SC_REGISTER: return dbg_cpu0_write_ctrl(adr, data) ? ERR_CRC : ERR_NONE;
case SC_WISHBONE: return dbg_wb_write32(adr, data) ? ERR_CRC : ERR_NONE;
case SC_TRACE: return 0;
default: return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_read_block(unsigned long adr, unsigned long *data, int len) {
debug("rb %d\n", gdb_chain);
switch (gdb_chain) {
case SC_WISHBONE: return dbg_wb_read_block32(adr, data, len) ? ERR_CRC : ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_write_block(unsigned long adr, unsigned long *data, int len) {
debug("wb %d\n", gdb_chain);
switch (gdb_chain) {
case SC_WISHBONE: return dbg_wb_write_block32(adr, data, len) ? ERR_CRC : ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_set_chain(int chain) {
debug("set_chain %d\n", chain);
switch (chain) {
case SC_RISC_DEBUG:
case SC_REGISTER:
case SC_TRACE:
case SC_WISHBONE: gdb_chain = chain;
return ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
}
 
 
 
/************************
JTAG Server Routines
************************/
 
unsigned int serverIP = 0;
unsigned int serverPort = 0;
unsigned int server_fd = 0;
unsigned int gdb_fd = 0;
static int gdb_read(void*, int);
static int gdb_write(void*, int);
static void ProtocolClean(int, int32_t);
 
static int tcp_level = 0;
 
/* Added by CZ 24/05/01 */
int GetServerSocket(const char* name, const char* proto, int port) {
struct servent *service;
struct protoent *protocol;
struct sockaddr_in sa;
struct hostent *hp;
int sockfd;
char myname[256];
int flags;
char sTemp[256];
 
/* First, get the protocol number of TCP */
if (!(protocol = getprotobyname(proto))) {
sprintf(sTemp, "Unable to load protocol \"%s\"", proto);
perror(sTemp);
return 0;
}
tcp_level = protocol->p_proto; /* Save for later */
 
/* If we weren't passed a non standard port, get the port
from the services directory. */
if (!port && (service = getservbyname(name, protocol->p_name)))
port = ntohs(service->s_port);
/* Create the socket using the TCP protocol */
if ((sockfd = socket(PF_INET, SOCK_STREAM, protocol->p_proto)) < 0) {
perror("Unable to create socket");
return 0;
}
flags = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&flags, sizeof(int)) < 0) {
sprintf(sTemp, "Can not set SO_REUSEADDR option on socket %d", sockfd);
perror(sTemp);
close(sockfd);
return 0;
}
 
/* The server should also be non blocking. Get the current flags. */
if((flags = fcntl(sockfd, F_GETFL, 0)) < 0) {
sprintf(sTemp, "Unable to get flags for socket %d", sockfd);
perror(sTemp);
close(sockfd);
return 0;
}
 
/* Set the nonblocking flag */
if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
sprintf(sTemp, "Unable to set flags for socket %d to value 0x%08x",
sockfd, flags | O_NONBLOCK);
perror(sTemp);
close(sockfd);
return 0;
}
 
/* Find out what our address is */
memset(&sa, 0, sizeof(struct sockaddr_in));
gethostname(myname, sizeof(myname));
if(!(hp = gethostbyname(myname))) {
perror("Unable to read hostname");
close(sockfd);
return 0;
}
/* Bind our socket to the appropriate address */
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons(port);
if(bind(sockfd, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)) < 0) {
sprintf(sTemp, "Unable to bind socket %d to port %d", sockfd, port);
perror(sTemp);
close(sockfd);
return 0;
}
serverIP = sa.sin_addr.s_addr;
flags = sizeof(struct sockaddr_in);
if(getsockname(sockfd, (struct sockaddr*)&sa, &flags) < 0) {
sprintf(sTemp, "Unable to get socket information for socket %d", sockfd);
perror(sTemp);
close(sockfd);
return 0;
}
serverPort = ntohs(sa.sin_port);
 
/* Set the backlog to 1 connections */
if(listen(sockfd, 1) < 0) {
sprintf(sTemp, "Unable to set backlog on socket %d to %d", sockfd, 1);
perror(sTemp);
close(sockfd);
return 0;
}
 
return sockfd;
}
 
void HandleServerSocket(Boolean block) {
struct pollfd fds[2];
int n;
rebuild:
n = 0;
if(!server_fd && !gdb_fd) return;
 
if(server_fd) {
fds[n].fd = server_fd;
fds[n].events = POLLIN;
fds[n++].revents = 0;
}
if(gdb_fd) {
fds[n].fd = gdb_fd;
fds[n].events = POLLIN;
fds[n++].revents = 0;
}
 
while(1) {
switch(poll(fds, n, -1)) {
case 0:
case -1:
if(errno == EINTR) continue;
perror("poll");
server_fd = 0;
return;
default:
/* Make sure to handle the gdb port first! */
if (gdb_fd && (fds[0].revents && !server_fd || fds[1].revents && server_fd)) {
int revents = server_fd ? fds[1].revents : fds[0].revents;
if (revents & POLLIN) GDBRequest();
else {/* Error Occurred */
fprintf(stderr, "Received flags 0x%08x on gdb socket. Shutting down.\n", revents);
close(gdb_fd);
gdb_fd = 0;
}
}
if(fds[0].revents && server_fd) {
if(fds[0].revents & POLLIN) {
JTAGRequest();
goto rebuild;
} else { /* Error Occurred */
fprintf(stderr, "Received flags 0x%08x on server. Shutting down.\n", fds[0].revents);
close(server_fd);
server_fd = 0;
serverPort = 0;
serverIP = 0;
return;
}
}
break;
} /* End of switch statement */
} /* End of while statement */
}
 
void JTAGRequest() {
struct sockaddr_in sa;
struct sockaddr* addr = (struct sockaddr*)&sa;
int n = sizeof(struct sockaddr_in);
int fd = accept(server_fd, addr, &n);
int on_off = 0; /* Turn off Nagel's algorithm on the socket */
int flags;
char sTemp[256];
 
if(fd < 0) {
/* This is valid, because a connection could have started,
and then terminated due to a protocol error or user
initiation before the accept could take place. */
if(errno != EWOULDBLOCK && errno != EAGAIN) {
perror("accept");
close(server_fd);
server_fd = 0;
serverPort = 0;
serverIP = 0;
}
return;
}
 
if(gdb_fd) {
close(fd);
return;
}
 
if((flags = fcntl(fd, F_GETFL, 0)) < 0) {
sprintf(sTemp, "Unable to get flags for gdb socket %d", fd);
perror(sTemp);
close(fd);
return;
}
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
sprintf(sTemp, "Unable to set flags for gdb socket %d to value 0x%08x",
fd, flags | O_NONBLOCK);
perror(sTemp);
close(fd);
return;
}
 
if(setsockopt(fd, tcp_level, TCP_NODELAY, &on_off, sizeof(int)) < 0) {
sprintf(sTemp, "Unable to disable Nagel's algorithm for socket %d.\nsetsockopt", fd);
perror(sTemp);
close(fd);
return;
}
 
gdb_fd = fd;
}
 
void GDBRequest() {
JTAGProxyWriteMessage msg_write;
JTAGProxyReadMessage msg_read;
JTAGProxyChainMessage msg_chain;
JTAGProxyWriteResponse resp_write;
JTAGProxyReadResponse resp_read;
JTAGProxyChainResponse resp_chain;
JTAGProxyBlockWriteMessage *msg_bwrite;
JTAGProxyBlockReadMessage msg_bread;
JTAGProxyBlockWriteResponse resp_bwrite;
JTAGProxyBlockReadResponse *resp_bread;
char *buf;
unsigned long long data;
uint32_t command, length;
int len, i;
int err = 0;
 
/* First, we must read the incomming command */
if(gdb_read(&command, sizeof(uint32_t)) < 0) {
if(gdb_fd) {
perror("gdb socket - 1");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
if(gdb_read(&length, sizeof(uint32_t)) < 0) {
if(gdb_fd) {
perror("gdb socket - 2");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
length = ntohl(length);
 
/* Now, verify the protocol and implement the command */
switch(ntohl(command)) {
case JTAG_COMMAND_WRITE:
if(length != sizeof(msg_write) - 8) {
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR);
return;
}
buf = (char*)&msg_write;
if(gdb_read(&buf[8], length) < 0) {
if(gdb_fd) {
perror("gdb socket - 3");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
msg_write.address = ntohl(msg_write.address);
msg_write.data_H = ntohl(msg_write.data_H);
msg_write.data_L = ntohl(msg_write.data_L);
err = gdb_write_reg(msg_write.address, msg_write.data_L);
resp_write.status = htonl(err);
if(gdb_write(&resp_write, sizeof(resp_write)) < 0) {
if(gdb_fd) {
perror("gdb socket - 4");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
break;
case JTAG_COMMAND_READ:
if(length != sizeof(msg_read) - 8) {
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR);
return;
}
buf = (char*)&msg_read;
if(gdb_read(&buf[8], length) < 0) {
if(gdb_fd) {
perror("gdb socket - 5");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
msg_read.address = ntohl(msg_read.address);
err = gdb_read_reg(msg_read.address, (unsigned long *)&resp_read.data_L);
resp_read.status = htonl(err);
resp_read.data_H = 0;
resp_read.data_L = htonl(resp_read.data_L);
if(gdb_write(&resp_read, sizeof(resp_read)) < 0) {
if(gdb_fd) {
perror("gdb socket - 6");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
break;
case JTAG_COMMAND_BLOCK_WRITE:
if(length < sizeof(JTAGProxyBlockWriteMessage)-8) {
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR);
return;
}
if(!(buf = (char*)malloc(8+length))) {
ProtocolClean(length, JTAG_PROXY_OUT_OF_MEMORY);
return;
}
msg_bwrite = (JTAGProxyBlockWriteMessage*)buf;
if(gdb_read(&buf[8], length) < 0) {
if(gdb_fd) {
perror("gdb socket - 5");
close(gdb_fd);
gdb_fd = 0;
}
free(buf);
return;
}
msg_bwrite->address = ntohl(msg_bwrite->address);
msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters);
for(i=0;i<msg_bwrite->nRegisters;i++) {
msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]);
}
err = gdb_write_block(msg_bwrite->address, (unsigned long*)msg_bwrite->data, msg_bwrite->nRegisters * 4);
resp_bwrite.status = htonl(err);
free(buf);
msg_bwrite = (JTAGProxyBlockWriteMessage *)NULL;
buf = (char *)msg_bwrite;
if(gdb_write(&resp_bwrite, sizeof(resp_bwrite)) < 0) {
if(gdb_fd) {
perror("gdb socket - 4");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
break;
case JTAG_COMMAND_BLOCK_READ:
if(length != sizeof(msg_bread) - 8) {
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR);
return;
}
buf = (char*)&msg_bread;
if(gdb_read(&buf[8], length) < 0) {
if(gdb_fd) {
perror("gdb socket - 5");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
msg_bread.address = ntohl(msg_bread.address);
msg_bread.nRegisters = ntohl(msg_bread.nRegisters);
len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1);
if(!(buf = (char*)malloc(len))) {
ProtocolClean(0, JTAG_PROXY_OUT_OF_MEMORY);
return;
}
resp_bread = (JTAGProxyBlockReadResponse*)buf;
err = gdb_read_block(msg_bread.address, (unsigned long*)resp_bread->data, msg_bread.nRegisters * 4);
for(i=0;i<msg_bread.nRegisters;i++) {
/* Read previous, address next one. */
resp_bread->data[i] = htonl(resp_bread->data[i]);
}
resp_bread->status = htonl(err);
resp_bread->nRegisters = htonl(msg_bread.nRegisters);
if(gdb_write(resp_bread, len) < 0) {
if(gdb_fd) {
perror("gdb socket - 6");
close(gdb_fd);
gdb_fd = 0;
}
free(buf);
return;
}
free(buf);
resp_bread = (JTAGProxyBlockReadResponse *)NULL;
buf = (char *)resp_bread;
break;
case JTAG_COMMAND_CHAIN:
if(length != sizeof(msg_chain) - 8) {
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR);
return;
}
buf = (char*)&msg_chain;
if(gdb_read(&buf[8], sizeof(msg_chain)-8) < 0) {
if(gdb_fd) {
perror("gdb socket - 7");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
msg_chain.chain = htonl(msg_chain.chain);
err = gdb_set_chain(msg_chain.chain);
resp_chain.status = htonl(err);
if(gdb_write(&resp_chain, sizeof(resp_chain)) < 0) {
if(gdb_fd) {
perror("gdb socket - 8");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
break;
default:
perror("Unknown JTAG command.");
ProtocolClean(length, JTAG_PROXY_COMMAND_NOT_IMPLEMENTED);
break;
}
}
 
static void ProtocolClean(int length, int32_t err) {
char buf[4096];
 
err = htonl(err);
if((gdb_read(buf, length) < 0) || (gdb_write(&err, sizeof(err)) < 0) && gdb_fd) {
perror("gdb socket - 9");
close(gdb_fd);
gdb_fd = 0;
}
}
 
static int gdb_write(void* buf, int len) {
int n;
char* w_buf = (char*)buf;
struct pollfd block;
 
while(len) {
if((n = write(gdb_fd, w_buf, len)) < 0) {
switch(errno) {
case EWOULDBLOCK: /* or EAGAIN */
/* We've been called on a descriptor marked
for nonblocking I/O. We better simulate
blocking behavior. */
block.fd = gdb_fd;
block.events = POLLOUT;
block.revents = 0;
poll(&block, 1, -1);
continue;
case EINTR:
continue;
case EPIPE:
close(gdb_fd);
gdb_fd = 0;
return -1;
default:
return -1;
}
} else {
len -= n;
w_buf += n;
}
}
return 0;
}
 
static int gdb_read(void* buf, int len) {
int n;
char* r_buf = (char*)buf;
struct pollfd block;
 
while(len) {
if((n = read(gdb_fd, r_buf, len)) < 0) {
switch(errno) {
case EWOULDBLOCK: /* or EAGAIN */
/* We've been called on a descriptor marked
for nonblocking I/O. We better simulate
blocking behavior. */
block.fd = gdb_fd;
block.events = POLLIN;
block.revents = 0;
poll(&block, 1, -1);
continue;
case EINTR:
continue;
default:
return -1;
}
} else if(n == 0) {
close(gdb_fd);
gdb_fd = 0;
return -1;
} else {
len -= n;
r_buf += n;
}
}
return 0;
}
/jp-io.c
0,0 → 1,443
/* jp-io.c -- Low level JTAG communications
Copyright (C) 2001 Marko Mlinar, markom@opencores.org
 
Code for TCP/IP copied from gdb, by Chris Ziomkowski
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* This handles all the low-level io with the selected cable */
 
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/io.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
 
#include <sys/socket.h>
#include <sys/un.h>
 
#include "jp.h"
 
static int jp_parallel_init();
static void jp_parallel_out(uint8_t value);
static uint8_t jp_parallel_in();
static int jp_parallel_opt(int c, char *str);
 
static void jp_phys_wait();
 
static int jp_rtl_sim_init();
static void jp_rtl_sim_out(uint8_t value);
static uint8_t jp_rtl_sim_in();
static void jp_rtl_sim_wait();
static int jp_rtl_sim_opt(int c, char *str);
 
static int jp_vpi_init();
static void jp_vpi_out(uint8_t value);
static uint8_t jp_vpi_in();
static void jp_vpi_wait();
static int jp_vpi_opt(int c, char *str);
 
static uint8_t jp_xpc3_in();
static void jp_xpc3_out(uint8_t value);
 
static uint8_t jp_xess_in();
static void jp_xess_out(uint8_t value);
 
static struct jtag_cable {
const char *name;
uint8_t (*in_func)();
void (*out_func)(uint8_t);
int (*init_func)();
void (*wait_func)();
int (*opt_func)(int c, char *str);
const char *opts;
const char *help;
} jtag_cables[] = {
{ "rtl_sim", jp_rtl_sim_in, jp_rtl_sim_out, jp_rtl_sim_init, jp_rtl_sim_wait,
jp_rtl_sim_opt, "d:",
"-d [directory] Directory in which gdb_in.dat/gdb_out.dat may be found\n" },
{ "vpi", jp_vpi_in, jp_vpi_out, jp_vpi_init, jp_vpi_wait, jp_vpi_opt, "s:",
"-s [socket] Location of socket that the vpi module created\n" },
{ "xpc3", jp_xpc3_in, jp_xpc3_out, jp_parallel_init, jp_phys_wait,
jp_parallel_opt, "p:",
"-p [port] Which port to use when communicateing with the parport hardware (eg. 0x378)\n" },
{ "xess", jp_xess_in, jp_xess_out, jp_parallel_init, jp_phys_wait,
jp_parallel_opt, "p:",
"-p [port] Which port to use when communicateing with the parport hardware (eg. 0x378)\n" },
{ NULL, NULL, NULL, NULL } };
 
static struct jtag_cable *jtag_cable_in_use = NULL; /* The current selected cable */
 
/* Only used for the parport */
static int base = 0x378;
 
/* Only used in the vpi */
static int vpi_comm;
static char *sock_loc = "/tmp/jp-vpi";
 
/* Only used for the rtl_sim */
static char *gdb_in = "gdb_in.dat";
static char *gdb_out = "gdb_out.dat";
 
void jp_out (uint8_t value)
{
/* finally call the cable-specific out-function */
jtag_cable_in_use->out_func(value);
 
if(!(value & 1))
debug("[%x%c]", (value & TDI_BIT) != 0, (value & TMS_BIT) ? '^' : '_');
flush_debug();
}
 
/* Receive a byte from the board. */
uint8_t jp_in()
{
int data;
 
/* Get the data from the board */
data = jtag_cable_in_use->in_func();
 
debug(" R%01X ", data);
flush_debug();
return data;
}
 
/* waits */
void jp_wait()
{
jtag_cable_in_use->wait_func();
}
 
/* Selects a cable for use, returns non-null on success */
int jp_select_cable(const char *cable)
{
int i;
 
for(i = 0; jtag_cables[i].name; i++) {
if(!strcmp(cable, jtag_cables[i].name)) {
jtag_cable_in_use = &jtag_cables[i];
return 1;
}
}
 
return 0;
}
 
/* Calls the init-fucntion of the cable */
int jp_init_cable()
{
return jtag_cable_in_use->init_func();
}
 
/* Parses command-line options specific to the selected cable */
int jp_cable_opt(int c, char *str)
{
return jtag_cable_in_use->opt_func(c, str);
}
 
const char *jp_get_cable_args()
{
return jtag_cable_in_use->opts;
}
 
/* Prints a (short) useage message for each availible cable */
void jp_print_cable_help()
{
int i;
printf("Availible cables: ");
 
for(i = 0; jtag_cables[i].name; i++) {
if(i)
printf(", ");
printf(jtag_cables[i].name);
}
 
printf("\n\nOptions availible for the cables:\n");
for(i = 0; jtag_cables[i].name; i++) {
if(!jtag_cables[i].help)
continue;
printf(" %s:\n %s", jtag_cables[i].name, jtag_cables[i].help);
}
}
 
/*-------------------------------------[ Parallel port specific functions ]---*/
static int jp_parallel_init()
{
if (ioperm(base, 3, 1)) {
fprintf(stderr, "Couldn't get the port at %x\n", base);
perror("Root privileges are required.\n");
return 0;
}
printf("Connected to parallel port at %x\n", base);
printf("Dropping root privileges.\n");
setreuid(getuid(), getuid());
return 1;
}
 
static void jp_parallel_out(uint8_t value)
{
outb(value, LPT_WRITE);
}
 
static uint8_t jp_parallel_in()
{
return inb(LPT_READ);
}
 
static int jp_parallel_opt(int c, char *str)
{
switch(c) {
case 'p':
if(!sscanf(str, "%x", &base)) {
fprintf(stderr, "p parameter must have a hex number as parameter\n");
return 0;
}
break;
default:
fprintf(stderr, "Unknown parameter '%c'\n", c);
return 0;
}
return 1;
}
 
/*-----------------------------------------[ Physical board wait function ]---*/
static void jp_phys_wait()
{
/* FIXME: this needs some real TLC */
int i;
volatile int j;
for(i = 0; i < 1000; i++)
j = i;
}
 
/*----------------------------------------------[ xpc3 specific functions ]---*/
static void jp_xpc3_out(uint8_t value)
{
uint8_t out = 0;
 
/* First convert the bits in value byte to the ones that the cable wants */
if(value & TCLK_BIT)
out |= 0x02; /* D1 pin 3 */
if(value & TRST_BIT)
out |= 0x10; /* Not used */
if(value & TDI_BIT)
out |= 0x01; /* D0 pin 2 */
if(value & TMS_BIT)
out |= 0x04; /* D2 pin 4 */
 
jp_parallel_out(out);
}
 
static uint8_t jp_xpc3_in()
{
uint8_t in;
 
in = jp_parallel_in();
 
if(in & 0x10) /* S6 pin 13 */
return 1;
return 0;
}
 
/*----------------------------------------------[ xess specific functions ]---*/
static void jp_xess_out(uint8_t value)
{
uint8_t out = 0;
 
/* First convert the bits in value byte to the ones that the cable wants */
if(value & TCLK_BIT)
out |= 0x04; /* D2 pin 4 */
if(value & TRST_BIT)
out |= 0x08; /* D3 pin 5 */
if(value & TDI_BIT)
out |= 0x10; /* D4 pin 6 */
if(value & TMS_BIT)
out |= 0x20; /* D3 pin 5 */
 
jp_parallel_out(out);
}
 
static uint8_t jp_xess_in()
{
uint8_t in;
 
in = jp_parallel_in();
 
if(in & 0x20) /* S5 pin 12*/
return 1;
return 0;
}
 
/*-------------------------------------------[ rtl_sim specific functions ]---*/
static int jp_rtl_sim_init()
{
FILE *fin = fopen (gdb_in, "wt+");
if(!fin) {
fprintf(stderr, "Can not open %s\n", gdb_in);
return 0;
}
fclose(fin);
return 1;
}
 
static void jp_rtl_sim_out(uint8_t value)
{
FILE *fout;
int num_read;
int r;
fout = fopen(gdb_in, "wt+");
fprintf(fout, "F\n");
fclose(fout);
fout = fopen(gdb_out, "wt+");
fprintf(fout, "%02X\n", value);
fclose(fout);
do {
fout = fopen(gdb_out, "rt");
r = fscanf(fout,"%x", &num_read);
fclose(fout);
} while(!r || (num_read != (0x10 | value)));
}
 
static uint8_t jp_rtl_sim_in()
{
FILE *fin = 0;
char ch;
uint8_t data;
while(1) {
fin = fopen(gdb_in, "rt");
if(!fin)
continue;
ch = fgetc(fin);
fclose(fin);
if((ch != '0') && (ch != '1'))
continue;
else
break;
}
data = ch == '1' ? 1 : 0;
return data;
}
 
static void jp_rtl_sim_wait()
{
usleep(1000);
}
 
static int jp_rtl_sim_opt(int c, char *str)
{
switch(c) {
case 'd':
if(!(gdb_in = malloc(strlen(str) + 12))) { /* 12 == strlen("gdb_in.dat") + 2 */
fprintf(stderr, "Unable to allocate enough memory\n");
return 0;
}
if(!(gdb_out = malloc(strlen(str) + 13))) { /* 13 == strlen("gdb_out.dat") + 2 */
fprintf(stderr, "Unable to allocate enough memory\n");
free(gdb_in);
return 0;
}
 
sprintf(gdb_in, "%s/gdb_in.dat", str);
sprintf(gdb_out, "%s/gdb_out.dat", str);
break;
default:
fprintf(stderr, "Unknown parameter '%c'\n", c);
return 0;
}
return 1;
}
 
/*-----------------------------------------------[ VPI specific functions ]---*/
static int jp_vpi_init()
{
struct sockaddr_un addr;
 
if((vpi_comm = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "Unable to create socket (%s)\n", strerror(errno));
return 0;
}
 
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, sock_loc);
 
if(connect(vpi_comm, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
fprintf(stderr, "Unable to connect to %s (%s)\n", addr.sun_path,
strerror(errno));
return 0;
}
return 1;
}
 
static void jp_vpi_out(uint8_t value)
{
uint8_t ack;
 
/* Send the data to the socket */
write(vpi_comm, &value, 1);
 
do {
/* Ok, read the data */
read(vpi_comm, &ack, 1);
} while(ack != (value | 0x10));
}
 
static uint8_t jp_vpi_in()
{
uint8_t dat;
 
/* ask vpi to send us the out-bit */
dat = 0x80;
write(vpi_comm, &dat, 1);
 
/* Wait and read the data */
read(vpi_comm, &dat, 1);
 
if(dat > 1)
fprintf(stderr, "Unexpected value: %i\n", dat);
 
return dat;
}
 
static void jp_vpi_wait()
{
uint8_t dat = 0x81;
 
/* Get the sim to reply when the timeout has been reached */
write(vpi_comm, &dat, 1);
 
/* block, waiting for the data */
read(vpi_comm, &dat, 1);
}
 
static int jp_vpi_opt(int c, char *str)
{
switch(c) {
case 's':
if(!(sock_loc = strdup(str))) {
fprintf(stderr, "Unable to allocate memory\n");
return 0;
}
break;
default:
fprintf(stderr, "Unknown parameter '%c'\n", c);
return 0;
}
return 1;
}
/jp.h
0,0 → 1,41
 
#define LPT_READ (base+1)
#define LPT_WRITE base
 
#define TCLK_BIT (0x01)
#define TRST_BIT (0x02)
#define TDI_BIT (0x04)
#define TMS_BIT (0x08)
#define TDO_BIT (0x20)
#define TMS (0x02)
#define TDI (0x01)
 
#ifdef DEBUG
#define debug printf
#else
#define debug
#endif
 
#ifdef DEBUG2
#define debug2 printf
#else
#define debug2
#endif
 
#if (DEBUG) || (DEBUG2)
#define flush_debug() fflush(stdout)
#else
#define flush_debug()
#endif
 
void jp_out (uint8_t value);
uint8_t jp_in();
int jp_select_cable(const char *cable);
void jp_wait();
int jp_cable_opt(int c, char *str);
void jp_print_cable_help();
const char *jp_get_cable_args();
int jp_init_cable();
 
# define NUM_RETRIES (16)
# define JTAG_RETRY_WAIT() usleep (1000)
/jp2.h
0,0 → 1,76
#ifndef _JP2_H_
#define _JP2_H_
 
#define Boolean int
#define false 0
#define true 1
 
/* Selects crc trailer size in bits. Currently supported: 8 */
#define CRC_SIZE (8)
 
/* Scan chain size in bits. */
#define SC_SIZE (4)
 
#ifndef ULONGEST
#define ULONGEST unsigned long
#endif
 
extern unsigned int serverPort;
extern unsigned int server_fd;
extern void HandleServerSocket(Boolean block);
 
extern int err;
extern void JTAGRequest(void);
extern void GDBRequest(void);
 
/* read a word from wishbone */
int dbg_wb_read32(unsigned long adr, unsigned long *data);
 
/* write a word to wishbone */
int dbg_wb_write32(unsigned long adr, unsigned long data);
 
/* read a block from wishbone */
int dbg_wb_read_block32(unsigned long adr, unsigned long *data, int len);
 
/* write a block to wishbone */
int dbg_wb_write_block32(unsigned long adr, unsigned long *data, int len);
 
/* read a register from cpu */
int dbg_cpu0_read(unsigned long adr, unsigned long *data);
 
/* read a register from cpu module */
int dbg_cpu0_read_ctrl(unsigned long adr, unsigned char *data);
 
/* write a cpu register */
int dbg_cpu0_write(unsigned long adr, unsigned long data);
 
/* write a cpu module register */
int dbg_cpu0_write_ctrl(unsigned long adr, unsigned char data);
 
 
#define DC_SIZE 4
#define DC_STATUS_SIZE 4
 
#define DC_WISHBONE 0
#define DC_CPU0 1
#define DC_CPU1 2
 
#define DI_GO 0
#define DI_READ_CMD 1
#define DI_WRITE_CMD 2
#define DI_READ_CTRL 3
#define DI_WRITE_CTRL 4
 
#define DBG_CRC_SIZE 32
#define DBG_CRC_POLY 0x04c11db7
 
#define DBG_ERR_OK 0
#define DBG_ERR_CRC 8
 
#define NUM_SOFT_RETRIES 3
#define NUM_HARD_RETRIES 3
#define NUM_ACCESS_RETRIES 10
 
#define CHECK(x) check(__FILE__, __LINE__, (x))
#endif /* _JP2_H_ */
 
/gdb.h
0,0 → 1,169
/* config.h -- Simulator configuration header file
Copyright (C) 2001 Chris Ziomkowski, chris@asics.ws
This file is part of OpenRISC 1000 Architectural Simulator.
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#ifndef GDB_H
#define GDB_H
 
#include <sys/types.h>
#include <inttypes.h>
 
/* Possible errors are listed here. */
enum enum_errors /* modified <chris@asics.ws> CZ 24/05/01 */
{
/* Codes > 0 are for system errors */
 
ERR_NONE = 0,
ERR_CRC = -1,
ERR_MEM = -2,
JTAG_PROXY_INVALID_COMMAND = -3,
JTAG_PROXY_SERVER_TERMINATED = -4,
JTAG_PROXY_NO_CONNECTION = -5,
JTAG_PROXY_PROTOCOL_ERROR = -6,
JTAG_PROXY_COMMAND_NOT_IMPLEMENTED = -7,
JTAG_PROXY_INVALID_CHAIN = -8,
JTAG_PROXY_INVALID_ADDRESS = -9,
JTAG_PROXY_ACCESS_EXCEPTION = -10, /* Write to ROM */
JTAG_PROXY_INVALID_LENGTH = -11,
JTAG_PROXY_OUT_OF_MEMORY = -12,
};
 
/* All JTAG chains. */
enum jtag_chains
{
SC_GLOBAL, /* 0 Global BS Chain */
SC_RISC_DEBUG, /* 1 RISC Debug Interface chain */
SC_RISC_TEST, /* 2 RISC Test Chain */
SC_TRACE, /* 3 Trace Chain */
SC_REGISTER, /* Register Chain */
SC_WISHBONE, /* 5 Memory chain */
SC_BLOCK, /* Block Chains */
};
 
/* See JTAG documentation about these. */
#define JI_SIZE (4)
enum jtag_instr
{
JI_EXTEST,
JI_SAMPLE_PRELOAD,
JI_IDCODE,
JI_CHAIN_SELECT,
JI_INTEST,
JI_CLAMP,
JI_CLAMPZ,
JI_HIGHZ,
JI_DEBUG,
JI_BYPASS = 0xF
};
 
/* JTAG registers. */
#define JTAG_MODER (0x0)
#define JTAG_TSEL (0x1)
#define JTAG_QSEL (0x2)
#define JTAG_SSEL (0x3)
#define JTAG_RISCOP (0x4)
#define JTAG_RECWP0 (0x10)
#define JTAG_RECBP0 (0x1b)
 
/* This is repeated from gdb tm-or1k.h There needs to be
a better mechanism for tracking this, but I don't see
an easy way to share files between modules. */
 
typedef enum {
JTAG_COMMAND_READ = 1,
JTAG_COMMAND_WRITE = 2,
JTAG_COMMAND_BLOCK_READ = 3,
JTAG_COMMAND_BLOCK_WRITE = 4,
JTAG_COMMAND_CHAIN = 5,
} JTAG_proxy_protocol_commands;
 
/* Each transmit structure must begin with an integer
which specifies the type of command. Information
after this is variable. Make sure to have all information
aligned properly. If we stick with 32 bit integers, it
should be portable onto every platform. These structures
will be transmitted across the network in network byte
order.
*/
 
typedef struct {
uint32_t command;
uint32_t length;
uint32_t address;
uint32_t data_H;
uint32_t data_L;
} JTAGProxyWriteMessage;
 
typedef struct {
uint32_t command;
uint32_t length;
uint32_t address;
} JTAGProxyReadMessage;
 
typedef struct {
uint32_t command;
uint32_t length;
uint32_t address;
int32_t nRegisters;
uint32_t data[1];
} JTAGProxyBlockWriteMessage;
 
typedef struct {
uint32_t command;
uint32_t length;
uint32_t address;
int32_t nRegisters;
} JTAGProxyBlockReadMessage;
 
typedef struct {
uint32_t command;
uint32_t length;
uint32_t chain;
} JTAGProxyChainMessage;
 
/* The responses are messages specific, however convention
states the first word should be an error code. Again,
sticking with 32 bit integers should provide maximum
portability. */
 
typedef struct {
int32_t status;
} JTAGProxyWriteResponse;
 
typedef struct {
int32_t status;
uint32_t data_H;
uint32_t data_L;
} JTAGProxyReadResponse;
typedef struct {
int32_t status;
} JTAGProxyBlockWriteResponse;
 
typedef struct {
int32_t status;
int32_t nRegisters;
uint32_t data[1];
/* uint32_t data[nRegisters-1] still unread */
} JTAGProxyBlockReadResponse;
 
typedef struct {
int32_t status;
} JTAGProxyChainResponse;
 
#endif /* GDB_H */
/mc.h
0,0 → 1,111
/* mc.h -- Simulation of Memory Controller
Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
/* Prototypes */
#ifndef __MC_H
#define __MC_H
 
#define N_CE (8)
 
#define MC_CSR (0x00)
#define MC_POC (0x04)
#define MC_BA_MASK (0x08)
#define MC_CSC(i) (0x10 + (i) * 8)
#define MC_TMS(i) (0x14 + (i) * 8)
 
#define MC_ADDR_SPACE (MC_CSC(N_CE))
 
/* POC register field definition */
#define MC_POC_EN_BW_OFFSET 0
#define MC_POC_EN_BW_WIDTH 2
#define MC_POC_EN_MEMTYPE_OFFSET 2
#define MC_POC_EN_MEMTYPE_WIDTH 2
 
/* CSC register field definition */
#define MC_CSC_EN_OFFSET 0
#define MC_CSC_MEMTYPE_OFFSET 1
#define MC_CSC_MEMTYPE_WIDTH 2
#define MC_CSC_BW_OFFSET 4
#define MC_CSC_BW_WIDTH 2
#define MC_CSC_MS_OFFSET 6
#define MC_CSC_MS_WIDTH 2
#define MC_CSC_WP_OFFSET 8
#define MC_CSC_BAS_OFFSET 9
#define MC_CSC_KRO_OFFSET 10
#define MC_CSC_PEN_OFFSET 11
#define MC_CSC_SEL_OFFSET 16
#define MC_CSC_SEL_WIDTH 8
 
#define MC_CSC_MEMTYPE_SDRAM 0
#define MC_CSC_MEMTYPE_SSRAM 1
#define MC_CSC_MEMTYPE_ASYNC 2
#define MC_CSC_MEMTYPE_SYNC 3
 
#define MC_CSR_VALID 0xFF000703LU
#define MC_POC_VALID 0x0000000FLU
#define MC_BA_MASK_VALID 0x000000FFLU
#define MC_CSC_VALID 0x00FF0FFFLU
#define MC_TMS_SDRAM_VALID 0x0FFF83FFLU
#define MC_TMS_SSRAM_VALID 0x00000000LU
#define MC_TMS_ASYNC_VALID 0x03FFFFFFLU
#define MC_TMS_SYNC_VALID 0x01FFFFFFLU
#define MC_TMS_VALID 0xFFFFFFFFLU /* reg test compat. */
 
/* TMS register field definition SDRAM */
#define MC_TMS_SDRAM_TRFC_OFFSET 24
#define MC_TMS_SDRAM_TRFC_WIDTH 4
#define MC_TMS_SDRAM_TRP_OFFSET 20
#define MC_TMS_SDRAM_TRP_WIDTH 4
#define MC_TMS_SDRAM_TRCD_OFFSET 17
#define MC_TMS_SDRAM_TRCD_WIDTH 4
#define MC_TMS_SDRAM_TWR_OFFSET 15
#define MC_TMS_SDRAM_TWR_WIDTH 2
#define MC_TMS_SDRAM_WBL_OFFSET 9
#define MC_TMS_SDRAM_OM_OFFSET 7
#define MC_TMS_SDRAM_OM_WIDTH 2
#define MC_TMS_SDRAM_CL_OFFSET 4
#define MC_TMS_SDRAM_CL_WIDTH 3
#define MC_TMS_SDRAM_BT_OFFSET 3
#define MC_TMS_SDRAM_BL_OFFSET 0
#define MC_TMS_SDRAM_BL_WIDTH 3
 
/* TMS register field definition ASYNC */
#define MC_TMS_ASYNC_TWWD_OFFSET 20
#define MC_TMS_ASYNC_TWWD_WIDTH 6
#define MC_TMS_ASYNC_TWD_OFFSET 16
#define MC_TMS_ASYNC_TWD_WIDTH 4
#define MC_TMS_ASYNC_TWPW_OFFSET 12
#define MC_TMS_ASYNC_TWPW_WIDTH 4
#define MC_TMS_ASYNC_TRDZ_OFFSET 8
#define MC_TMS_ASYNC_TRDZ_WIDTH 4
#define MC_TMS_ASYNC_TRDV_OFFSET 0
#define MC_TMS_ASYNC_TRDV_WIDTH 8
 
/* TMS register field definition SYNC */
#define MC_TMS_SYNC_TTO_OFFSET 16
#define MC_TMS_SYNC_TTO_WIDTH 9
#define MC_TMS_SYNC_TWR_OFFSET 12
#define MC_TMS_SYNC_TWR_WIDTH 4
#define MC_TMS_SYNC_TRDZ_OFFSET 8
#define MC_TMS_SYNC_TRDZ_WIDTH 4
#define MC_TMS_SYNC_TRDV_OFFSET 0
#define MC_TMS_SYNC_TRDV_WIDTH 8
 
#endif
/jp-io-vpi.c
0,0 → 1,279
/* jp-io-vpi.c -- JTAG communications vpi plugin
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* This plugs into an rtl simulator via vpi */
 
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/un.h>
#include <errno.h>
 
#include <vpi_user.h>
 
/* The vpi<->jp connection is `mastered' by jp1. Therefore we just sit doing
* `nothing', waiting for jp1 to request or send us some data */
static uint8_t vpi_out; /* data that the sim gives to us */
 
static int jp_comm_m; /* The listening socket */
static int jp_comm; /* The socket for communitateing with jp1 */
 
static int jp_got_con; /* Have we got a connection ? */
 
static int count_comp; /* Has the predetermined cycle-count been reached ? */
static int jp_waiting; /* Is jp-waiting for count_comp ? */
 
int jp_check_con();
 
/*---------------------------------------------[ VPI interface to the sim ]---*/
/* Sends a byte from the sim */
int vpi_jp_out(char *xx)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
s_vpi_value value;
 
if(!argv) {
vpi_printf("$jp_out: missing destination argument\n");
vpi_free_object(argv);
return 0;
}
vpiHandle dat_to = vpi_scan(argv);
if(vpi_get(vpiType, dat_to) != vpiNet) {
vpi_printf("$jp_out: Must have a net as argument!!\n");
vpi_free_object(argv);
return 0;
}
 
value.format = vpiVectorVal;
vpi_get_value(dat_to, &value);
 
if((value.value.vector->bval & 1)) {
vpi_free_object(argv);
return 0;
}
vpi_out = value.value.vector->aval & 1;
 
vpi_free_object(argv);
 
return 0;
}
 
/* Sends a byte to the sim */
int vpi_jp_in(char *xx)
{
int ret;
uint8_t dat;
s_vpi_vecval vec;
 
s_vpi_value value;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv;
vpiHandle dat_to;
 
vpiHandle dat_to_index;
 
if(!jp_got_con) {
if(!jp_check_con())
return 0;
}
 
ret = read(jp_comm, &dat, 1);
if(!ret)
return 0;
if((ret == -1) && (errno == EAGAIN))
return 0;
 
if(dat & 0x80) {
switch(dat & 0x7f) {
case 0:
/* jp1 wants the TDO */
write(jp_comm, &vpi_out, 1);
return 0;
case 1:
/* jp wants a time-out */
if(count_comp)
write(jp_comm, &dat, 1); /* The value is irrelevent */
else
jp_waiting = 1;
return 0;
}
}
 
argv = vpi_iterate(vpiArgument, sys);
 
/* We got the data, acknowledge it and send it on to the sim */
if(!argv) {
vpi_printf("$jp_in: missing destination argument\n");
vpi_free_object(argv);
return 0;
}
dat_to = vpi_scan(argv);
if(vpi_get(vpiType, dat_to) != vpiMemory) {
vpi_printf("$jp_in: Must have a memory as argument!!\n");
vpi_free_object(argv);
return 0;
}
 
value.format = vpiVectorVal;
 
vec.aval = (dat & 0xf) | 0x10;
vec.bval = 0;
value.value.vector = &vec;
dat_to_index = vpi_handle_by_index(dat_to, 0);
vpi_put_value(dat_to_index, &value, 0, vpiNoDelay);
 
vpi_free_object(argv);
 
dat |= 0x10;
write(jp_comm, &dat, 1);
 
count_comp = 0;
 
return 0;
}
 
/* tells us that we reached a predetermined cycle count */
int jp_wait_time(char *xx)
{
uint8_t dat = 0;
if(jp_waiting) {
write(jp_comm, &dat, 1);
jp_waiting = 0;
}
count_comp = 1;
return 0;
}
 
/*---------------------------------------------------[ VPI<->jp functions ]---*/
int init_sock(char *xx)
{
struct sockaddr_un addr;
int ret;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
s_vpi_value value;
 
if(!argv) {
vpi_printf("$jp_init: missing destination argument\n");
return 0;
}
vpiHandle sock = vpi_scan(argv);
/*
if(vpi_get(vpiConstType, sock) != vpiStringConst) {
vpi_printf("$jp_init: Must have a string as argument!!\n");
vpi_free_object(argv);
return 0;
}
*/
 
value.format = vpiStringVal;
vpi_get_value(sock, &value);
 
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, value.value.str);
 
if((jp_comm_m = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "Unable to create comm socket\n");
return 0;
}
 
if(bind(jp_comm_m, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
fprintf(stderr, "Unable to bind to the unix socket %s\n", addr.sun_path);
return 0;
}
 
if(listen(jp_comm_m, 1) == -1) {
fprintf(stderr, "Unable to listen on %s (%s)\n", addr.sun_path,
strerror(errno));
return 0;
}
 
ret = fcntl(jp_comm_m, F_GETFL);
ret |= O_NONBLOCK;
fcntl(jp_comm_m, F_SETFL, ret);
 
jp_got_con = 0;
jp_waiting = 0;
printf("Just registered socket!!!\n");
return 0;
}
 
/* Checks to see if we got a connection */
int jp_check_con()
{
int ret;
 
if((jp_comm = accept(jp_comm_m, NULL, NULL)) == -1) {
if(errno == EAGAIN)
return 0;
fprintf(stderr, "Unable to accept connection (%s)\n", strerror(errno));
return 0;
}
 
/* Set the comm socket to non-blocking */
ret = fcntl(jp_comm, F_GETFL);
ret |= O_NONBLOCK;
fcntl(jp_comm, F_SETFL, ret);
 
jp_got_con = 1;
return 1;
}
 
/*------------------------------------------------------------[ VPI stuff ]---*/
static void jtag_register()
{
s_vpi_systf_data tf_data;
 
tf_data.type = vpiSysTask;
tf_data.tfname = "$jp_in";
tf_data.calltf = vpi_jp_in;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
vpi_register_systf(&tf_data);
 
tf_data.type = vpiSysTask;
tf_data.tfname = "$jp_out";
tf_data.calltf = vpi_jp_out;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
vpi_register_systf(&tf_data);
 
tf_data.type = vpiSysTask;
tf_data.tfname = "$jp_init";
tf_data.calltf = init_sock;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
vpi_register_systf(&tf_data);
 
tf_data.type = vpiSysTask;
tf_data.tfname = "$jp_wait_time";
tf_data.calltf = jp_wait_time;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
vpi_register_systf(&tf_data);
}
 
void (*vlog_startup_routines[])() = {
jtag_register,
0
};
/jp2.c
0,0 → 1,1235
/* jp2-linux.c -- JTAG protocol via parallel port for linux
Copyright(C) 2001 Marko Mlinar, markom@opencores.org
Code for TCP/IP copied from gdb, by Chris Ziomkowski
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* Establishes jtag proxy server and communicates with parallel
port directly. Requires root access. */
 
#include <assert.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <sys/types.h>
 
#include "mc.h"
#include "gdb.h"
#include "jp2.h"
#include "jp.h"
 
#define TC_RESET 0
#define TC_BRIGHT 1
#define TC_DIM 2
#define TC_UNDERLINE 3
#define TC_BLINK 4
#define TC_REVERSE 7
#define TC_HIDDEN 8
 
#define TC_BLACK 0
#define TC_RED 1
#define TC_GREEN 2
#define TC_YELLOW 3
#define TC_BLUE 4
#define TC_MAGENTA 5
#define TC_CYAN 6
#define TC_WHITE 7
 
#define SDRAM_BASE 0x00000000
#define SDRAM_SIZE 0x04000000
#define SRAM_BASE 0x40000000
#define SRAM_SIZE 0x04000000 // This is not ok
 
 
int err = 0;
int set_pc = 0;
int set_step = 0;
int waiting = 0;
 
/* Scan chain info. */
static int chain_addr_size[] = { 0, 32, 0, 0, 5, 32, 32};
static int chain_data_size[] = { 0, 32, 0, 32, 32, 32, 32};
static int chain_is_valid[] = { 0, 1, 0, 1, 1, 1, 1};
static int chain_has_crc[] = { 0, 1, 0, 1, 1, 1, 1};
static int chain_has_rw[] = { 0, 1, 0, 0, 1, 1, 1};
 
/* Currently selected scan chain - just to prevent unnecessary
transfers. */
static int current_chain = -1;
 
/* The chain that should be currently selected. */
static int dbg_chain = -1;
 
/* Crc of current read or written data. */
static int crc_r, crc_w = 0;
 
/* Address of previous read */
static unsigned long prev_regno = 0;
 
/* Generates new crc, sending in new bit input_bit */
static unsigned long crc_calc(unsigned long crc, int input_bit) {
unsigned long d = (input_bit&1) ? 0xfffffff : 0x0000000;
unsigned long crc_32 = ((crc >> 31)&1) ? 0xfffffff : 0x0000000;
crc <<= 1;
return crc ^ (d ^ crc_32) & DBG_CRC_POLY;
}
 
/* Writes TCLK=0, TRST=1, TMS=bit1, TDI=bit0
and TCLK=1, TRST=1, TMS=bit1, TDI=bit0 */
static void jp2_write_JTAG(uint8_t packet) {
uint8_t data = TRST_BIT;
if(packet & 1) data |= TDI_BIT;
if(packet & 2) data |= TMS_BIT;
jp_out(data);
jp_wait();
crc_w = crc_calc(crc_w, packet&1);
 
/* rise clock */
jp_out(data | TCLK_BIT);
jp_wait();
}
 
/* Reads TDI. */
static int jp2_read_JTAG() {
uint8_t data;
data = jp_in();
crc_r = crc_calc(crc_r, data);
return data;
}
 
/* Writes bitstream. LS bit first if len < 0, MS bit first if len > 0. */
static void jp2_write_stream(ULONGEST stream, int len, int set_last_bit) {
int i;
if (len < 0) {
len = -len;
debug("writeL%d(", len);
for(i = 0; i < len - 1; i++)
jp2_write_JTAG((stream >> i) & 1);
 
if(set_last_bit) jp2_write_JTAG((stream >>(len - 1))& 1 | TMS);
else jp2_write_JTAG((stream >>(len - 1))& 1);
} else {
debug("write%d(", len);
for(i = 0; i < len - 1; i++)
jp2_write_JTAG((stream >> (len - 1 - i)) & 1);
 
if(set_last_bit) jp2_write_JTAG((stream >> 0) & 1 | TMS);
else jp2_write_JTAG((stream >> 0)& 1);
}
debug(")\n");
}
 
/* Gets bitstream. LS bit first if len < 0, MS bit first if len > 0. */
static ULONGEST jp2_read_stream(unsigned long stream, int len, int set_last_bit) {
int i;
ULONGEST data = 0;
if (len < 0) {
debug("readL(");
for(i = 0; i < len - 1; i++) {
jp2_write_JTAG((stream >> i) & 1); /* LSB first */
data |= jp2_read_JTAG() << i; /* LSB first */
}
if (set_last_bit) jp2_write_JTAG((stream >> (len - 1)) & 1 | TMS);
else jp2_write_JTAG((stream >> (len - 1)) & 1);
data |= jp2_read_JTAG() << (len - 1);
} else {
debug("read(");
for(i = 0; i < len - 1; i++) {
jp2_write_JTAG((stream >> (len - 1 - i)) & 1); /* MSB first */
data |= jp2_read_JTAG() << (len - 1 - i); /* MSB first */
}
if (set_last_bit) jp2_write_JTAG((stream >> 0) & 1 | TMS);
else jp2_write_JTAG((stream >> 0) & 1);
data |= jp2_read_JTAG() << 0;
}
debug(")\n");
return data;
}
 
/* Sets scan chain. */
void jtag_set_ir(int ir) {
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */
jp2_write_JTAG(TMS); /* SELECT_IR SCAN */
 
jp2_write_JTAG(0); /* CAPTURE_IR */
jp2_write_JTAG(0); /* SHIFT_IR */
/* write data, EXIT1_IR */
jp2_write_stream(ir, -JI_SIZE, 1);
 
jp2_write_JTAG(TMS); /* UPDATE_IR */
jp2_write_JTAG(0); /* IDLE */
current_chain = -1;
}
 
/* Resets JTAG
Writes TRST=0
and TRST=1 */
static void jp2_reset_JTAG() {
int i;
debug2("\nreset(");
jp_out(0);
JTAG_RETRY_WAIT();
/* In case we don't have TRST reset it manually */
for(i = 0; i < 8; i++) jp2_write_JTAG(TMS);
jp_out(TRST_BIT);
JTAG_RETRY_WAIT();
jp2_write_JTAG(0);
debug2(")\n");
}
 
/* Resets JTAG, and sets DEBUG scan chain */
static int dbg_reset() {
int err;
unsigned long id;
jp2_reset_JTAG();
 
/* read ID */
jtag_set_ir(JI_IDCODE);
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */
jp2_write_JTAG(0); /* CAPTURE_DR */
jp2_write_JTAG(0); /* SHIFT_DR */
/* read ID, EXIT1_DR */
crc_w = 0xffffffff;
id = jp2_read_stream(0, 32, 1);
jp2_write_JTAG(TMS); /* UPDATE_DR */
jp2_write_JTAG(0); /* IDLE */
printf("JTAG ID = %08x\n", id);
 
/* select debug scan chain and stay in it forever */
jtag_set_ir(JI_DEBUG);
current_chain = -1;
return DBG_ERR_OK;
}
 
/* counts retries and returns zero if we should abort */
/* TODO: dinamically adjust timings for jp2 */
static int retry_no = 0;
int retry_do() {
int i, err;
printf("RETRY\n");
//exit(2);
if (retry_no >= NUM_SOFT_RETRIES) {
if ((err = dbg_reset())) return err;
} else { /* quick reset */
for(i = 0; i < 8; i++) jp2_write_JTAG(TMS);
jp2_write_JTAG(0); /* go into IDLE state */
}
if (retry_no >= NUM_SOFT_RETRIES + NUM_HARD_RETRIES) {
retry_no = 0;
return 0;
}
retry_no++;
return 1;
}
 
/* resets retry counter */
void retry_ok() {
retry_no = 0;
}
 
/* Sets scan chain. */
int dbg_set_chain(int chain) {
int status, crc_generated, crc_read;
dbg_chain = chain;
 
try_again:
if (current_chain == chain) return DBG_ERR_OK;
current_chain = -1;
debug("\n");
debug2("set_chain %i\n", chain);
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */
jp2_write_JTAG(0); /* CAPTURE_DR */
jp2_write_JTAG(0); /* SHIFT_DR */
/* write data, EXIT1_DR */
crc_w = 0xffffffff;
jp2_write_stream((chain & 0xf | (1<<DC_SIZE)), DC_SIZE + 1, 0);
jp2_write_stream(crc_w, DBG_CRC_SIZE, 0);
crc_r = 0xffffffff;
status = jp2_read_stream(0, DC_STATUS_SIZE, 0);
crc_generated = crc_r;
crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1);
 
//printf("%x %x %x\n", status, crc_read, crc_generated);
/* CRCs must match, otherwise retry */
if (crc_read != crc_generated) {
if (retry_do()) goto try_again;
else return DBG_ERR_CRC;
}
/* we should read expected status value, otherwise retry */
if (status != 0) {
if (retry_do()) goto try_again;
else return status;
}
 
/* reset retry counter */
retry_ok();
 
jp2_write_JTAG(TMS); /* UPDATE_DR */
jp2_write_JTAG(0); /* IDLE */
current_chain = chain;
return DBG_ERR_OK;
}
 
/* sends out a command with 32bit address and 16bit length, if len >= 0 */
int dbg_command(int type, unsigned long adr, int len) {
int status, crc_generated, crc_read;
 
try_again:
dbg_set_chain(dbg_chain);
debug("\n");
debug2("comm %i\n", type);
 
/***** WRITEx *****/
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */
jp2_write_JTAG(0); /* CAPTURE_DR */
jp2_write_JTAG(0); /* SHIFT_DR */
/* write data, EXIT1_DR */
crc_w = 0xffffffff;
jp2_write_stream((DI_WRITE_CMD & 0xf | (0<<DC_SIZE)), DC_SIZE + 1, 0);
jp2_write_stream(type, 4, 0);
jp2_write_stream(adr, 32, 0);
assert(len > 0);
jp2_write_stream(len - 1, 16, 0);
jp2_write_stream(crc_w, DBG_CRC_SIZE, 0);
crc_r = 0xffffffff;
status = jp2_read_stream(0, DC_STATUS_SIZE, 0);
crc_generated = crc_r;
crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1);
 
/* CRCs must match, otherwise retry */
if (crc_read != crc_generated) {
if (retry_do()) goto try_again;
else return DBG_ERR_CRC;
}
/* we should read expected status value, otherwise retry */
if (status != 0) {
if (retry_do()) goto try_again;
else return status;
}
jp2_write_JTAG(TMS); /* UPDATE_DR */
jp2_write_JTAG(0); /* IDLE */
 
/* reset retry counter */
retry_ok();
return DBG_ERR_OK;
}
 
/* writes a ctrl reg */
int dbg_ctrl(int reset, int stall) {
int status, crc_generated, crc_read;
 
try_again:
dbg_set_chain(dbg_chain);
debug("\n");
debug2("ctrl\n");
 
/***** WRITEx *****/
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */
jp2_write_JTAG(0); /* CAPTURE_DR */
jp2_write_JTAG(0); /* SHIFT_DR */
/* write data, EXIT1_DR */
crc_w = 0xffffffff;
jp2_write_stream((DI_WRITE_CTRL & 0xf | (0<<DC_SIZE)), DC_SIZE + 1, 0);
jp2_write_stream(reset, 1, 0);
jp2_write_stream(stall, 1, 0);
jp2_write_stream(0, 50, 0);
jp2_write_stream(crc_w, DBG_CRC_SIZE, 0);
crc_r = 0xffffffff;
status = jp2_read_stream(0, DC_STATUS_SIZE, 0);
crc_generated = crc_r;
crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1);
 
/* CRCs must match, otherwise retry */
//printf("%x %x %x\n", status, crc_read, crc_generated);
if (crc_read != crc_generated) {
if (retry_do()) goto try_again;
else return DBG_ERR_CRC;
}
/* we should read expected status value, otherwise retry */
if (status != 0) {
if (retry_do()) goto try_again;
else return status;
}
jp2_write_JTAG(TMS); /* UPDATE_DR */
jp2_write_JTAG(0); /* IDLE */
 
/* reset retry counter */
retry_ok();
return DBG_ERR_OK;
}
 
/* reads control register */
int dbg_ctrl_read(int *reset, int *stall) {
int status, crc_generated, crc_read;
 
try_again:
dbg_set_chain(dbg_chain);
debug("\n");
debug2("ctrl_read\n");
 
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */
jp2_write_JTAG(0); /* CAPTURE_DR */
jp2_write_JTAG(0); /* SHIFT_DR */
/* write data, EXIT1_DR */
crc_w = 0xffffffff;
jp2_write_stream(DI_READ_CTRL | (0<<DC_SIZE), DC_SIZE + 1, 0);
jp2_write_stream(crc_w, DBG_CRC_SIZE, 0);
crc_r = 0xffffffff;
*reset = jp2_read_stream(0, 1, 0);
*stall = jp2_read_stream(0, 1, 0);
jp2_read_stream(0, 50, 0);
status = jp2_read_stream(0, DC_STATUS_SIZE, 0);
crc_generated = crc_r;
crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1);
/* CRCs must match, otherwise retry */
//printf("%x %x %x\n", status, crc_read, crc_generated);
if (crc_read != crc_generated) {
if (retry_do()) goto try_again;
else return DBG_ERR_CRC;
}
/* we should read expected status value, otherwise retry */
if (status != 0) {
if (retry_do()) goto try_again;
else return status;
}
jp2_write_JTAG(TMS); /* UPDATE_DR */
jp2_write_JTAG(0); /* IDLE */
 
/* reset retry counter */
retry_ok();
return DBG_ERR_OK;
}
/* issues a burst read/write */
int dbg_go(unsigned char *data, unsigned short len, int read) {
int status, crc_generated, crc_read;
int i;
 
try_again:
dbg_set_chain(dbg_chain);
debug("\n");
debug2("go len = %d\n", len);
 
jp2_write_JTAG(TMS); /* SELECT_DR SCAN */
jp2_write_JTAG(0); /* CAPTURE_DR */
jp2_write_JTAG(0); /* SHIFT_DR */
/* write data, EXIT1_DR */
crc_w = 0xffffffff;
jp2_write_stream(DI_GO | (0<<DC_SIZE), DC_SIZE + 1, 0);
if (!read) {
/* reverse byte ordering, since we must send in big endian */
for (i = 0; i < len; i++)
jp2_write_stream(data[i], 8, 0);
}
jp2_write_stream(crc_w, DBG_CRC_SIZE, 0);
crc_r = 0xffffffff;
if (read) {
/* reverse byte ordering, since we must send in big endian */
for (i = 0; i < len; i++)
data[i] = jp2_read_stream(data[i], 8, 0);
}
status = jp2_read_stream(0, DC_STATUS_SIZE, 0);
crc_generated = crc_r;
crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1);
/* CRCs must match, otherwise retry */
//printf("%x %x %x\n", status, crc_read, crc_generated);
if (crc_read != crc_generated) {
if (retry_do()) goto try_again;
else return DBG_ERR_CRC;
}
/* we should read expected status value, otherwise retry */
if (status != 0) {
if (retry_do()) goto try_again;
else return status;
}
jp2_write_JTAG(TMS); /* UPDATE_DR */
jp2_write_JTAG(0); /* IDLE */
 
/* reset retry counter */
retry_ok();
return DBG_ERR_OK;
}
 
/* read a word from wishbone */
int dbg_wb_read32(unsigned long adr, unsigned long *data) {
int err;
if ((err = dbg_set_chain(DC_WISHBONE))) return err;
if ((err = dbg_command(0x6, adr, 4))) return err;
if ((err = dbg_go((unsigned char*)data, 4, 1))) return err;
*data = ntohl(*data);
return err;
}
 
/* write a word to wishbone */
int dbg_wb_write32(unsigned long adr, unsigned long data) {
int err;
data = ntohl(data);
if ((err = dbg_set_chain(DC_WISHBONE))) return err;
if ((err = dbg_command(0x2, adr, 4))) return err;
if ((err = dbg_go((unsigned char*)&data, 4, 0))) return err;
return DBG_ERR_OK;
}
 
/* write a word to wishbone */
int dbg_wb_write16(unsigned long adr, unsigned short data) {
int err;
data = ntohs(data);
if ((err = dbg_set_chain(DC_WISHBONE))) return err;
if ((err = dbg_command(0x1, adr, 2))) return err;
if ((err = dbg_go((unsigned char*)&data, 2, 0))) return err;
return DBG_ERR_OK;
}
 
/* write a word to wishbone */
int dbg_wb_write8(unsigned long adr, unsigned long data) {
int err;
if ((err = dbg_set_chain(DC_WISHBONE))) return err;
if ((err = dbg_command(0x0, adr, 1))) return err;
if ((err = dbg_go((unsigned char*)&data, 1, 0))) return err;
return DBG_ERR_OK;
}
 
/* read a block from wishbone */
int dbg_wb_read_block32(unsigned long adr, unsigned long *data, int len) {
int i, err;
//printf("%08x %08x\n", adr, len);
if ((err = dbg_set_chain(DC_WISHBONE))) return err;
if ((err = dbg_command(0x6, adr, len))) return err;
if ((err = dbg_go((unsigned char*)data, len, 1))) return err;
for (i = 0; i < len / 4; i ++) data[i] = ntohl(data[i]);
//printf("%08x\n", err);
return DBG_ERR_OK;
}
 
/* read a block from wishbone */
int dbg_wb_read_block16(unsigned long adr, unsigned short *data, int len) {
int i, err;
//printf("%08x %08x\n", adr, len);
if ((err = dbg_set_chain(DC_WISHBONE))) return err;
if ((err = dbg_command(0x5, adr, len))) return err;
if ((err = dbg_go((unsigned char*)data, len, 1))) return err;
for (i = 0; i < len / 2; i ++) data[i] = ntohs(data[i]);
//printf("%08x\n", err);
return DBG_ERR_OK;
}
 
/* read a block from wishbone */
int dbg_wb_read_block8(unsigned long adr, unsigned char *data, int len) {
int i, err;
//printf("%08x %08x\n", adr, len);
if ((err = dbg_set_chain(DC_WISHBONE))) return err;
if ((err = dbg_command(0x4, adr, len))) return err;
if ((err = dbg_go((unsigned char*)data, len, 1))) return err;
//printf("%08x\n", err);
return DBG_ERR_OK;
}
 
/* write a block to wishbone */
int dbg_wb_write_block32(unsigned long adr, unsigned long *data, int len) {
int i, err;
for (i = 0; i < len / 4; i ++) data[i] = ntohl(data[i]);
if ((err = dbg_set_chain(DC_WISHBONE))) return err;
if ((err = dbg_command(0x2, adr, len))) return err;
if ((err = dbg_go((unsigned char*)data, len, 0))) return err;
return DBG_ERR_OK;
}
 
/* write a block to wishbone */
int dbg_wb_write_block16(unsigned long adr, unsigned short *data, int len) {
int i, err;
for (i = 0; i < len / 2; i ++) data[i] = ntohs(data[i]);
if ((err = dbg_set_chain(DC_WISHBONE))) return err;
if ((err = dbg_command(0x1, adr, len))) return err;
if ((err = dbg_go((unsigned char*)data, len, 0))) return err;
return DBG_ERR_OK;
}
 
/* write a block to wishbone */
int dbg_wb_write_block8(unsigned long adr, unsigned char *data, int len) {
int i, err;
if ((err = dbg_set_chain(DC_WISHBONE))) return err;
if ((err = dbg_command(0x0, adr, len))) return err;
if ((err = dbg_go((unsigned char*)data, len, 0))) return err;
return DBG_ERR_OK;
}
 
/* read a register from cpu */
int dbg_cpu0_read(unsigned long adr, unsigned long *data) {
int err;
if ((err = dbg_set_chain(DC_CPU0))) return err;
if ((err = dbg_command(0x6, adr, 4))) return err;
if ((err = dbg_go((unsigned char*)data, 4, 1))) return err;
*data = ntohl(*data);
return DBG_ERR_OK;
}
 
/* write a cpu register */
int dbg_cpu0_write(unsigned long adr, unsigned long data) {
int err;
data = ntohl(data);
if ((err = dbg_set_chain(DC_CPU0))) return err;
if ((err = dbg_command(0x2, adr, 4))) return err;
if ((err = dbg_go((unsigned char*)&data, 4, 0))) return err;
return DBG_ERR_OK;
}
 
/* read a register from cpu */
int dbg_cpu1_read(unsigned long adr, unsigned long *data) {
int err;
if ((err = dbg_set_chain(DC_CPU1))) return err;
if ((err = dbg_command(0x6, adr, 4))) return err;
if ((err = dbg_go((unsigned char*)data, 4, 1))) return err;
*data = ntohl(*data);
return DBG_ERR_OK;
}
 
/* write a cpu register */
int dbg_cpu1_write(unsigned long adr, unsigned long data) {
int err;
data = ntohl(data);
if ((err = dbg_set_chain(DC_CPU1))) return err;
if ((err = dbg_command(0x2, adr, 4))) return err;
if ((err = dbg_go((unsigned char*)&data, 4, 0))) return err;
return DBG_ERR_OK;
}
 
/* write a cpu module register */
int dbg_cpu1_write_reg(unsigned long adr, unsigned char data) {
int err;
if ((err = dbg_set_chain(DC_CPU1))) return err;
if ((err = dbg_ctrl(data & 2, data &1))) return err;
return DBG_ERR_OK;
}
 
/* read a register from cpu module */
int dbg_cpu1_read_ctrl(unsigned long adr, unsigned char *data) {
int err;
int r, s;
if ((err = dbg_set_chain(DC_CPU1))) return err;
if ((err = dbg_ctrl_read(&r, &s))) return err;
*data = (r << 1) | s;
return DBG_ERR_OK;
}
 
/* write a cpu module register */
int dbg_cpu0_write_ctrl(unsigned long adr, unsigned char data) {
int err;
if ((err = dbg_set_chain(DC_CPU0))) return err;
if ((err = dbg_ctrl(data & 2, data &1))) return err;
return DBG_ERR_OK;
}
 
/* read a register from cpu module */
int dbg_cpu0_read_ctrl(unsigned long adr, unsigned char *data) {
int err;
int r, s;
if ((err = dbg_set_chain(DC_CPU0))) return err;
if ((err = dbg_ctrl_read(&r, &s))) return err;
*data = (r << 1) | s;
return DBG_ERR_OK;
}
 
void check(char *fn, int l, int i) {
if (i != DBG_ERR_OK) {
fprintf(stderr, "%s:%d: Jtag error %d occured; exiting.\n", fn, l, i);
exit(1);
}
}
 
 
void test_sdram (void) {
unsigned long insn;
unsigned long i;
unsigned long data4_out[0x08];
unsigned long data4_in[0x08];
unsigned short data2_out[0x10];
unsigned short data2_in[0x10];
unsigned char data1_out[0x20];
unsigned char data1_in[0x20];
printf("Start SDRAM WR\n");
for (i=0x10; i<(SDRAM_SIZE+SDRAM_BASE); i=i<<1) {
//printf("0x%x: 0x%x\n", SDRAM_BASE+i, i);
CHECK(dbg_wb_write32(SDRAM_BASE+i, i));
}
printf("Start SDRAM RD\n");
for (i=0x10; i<(SDRAM_SIZE+SDRAM_BASE); i=i<<1) {
CHECK(dbg_wb_read32(SDRAM_BASE+i, &insn));
//printf("0x%x: 0x%x\n", SDRAM_BASE+i, insn);
if (i != insn) {
printf("SDRAM not OK");
exit (1);
}
}
 
printf("32-bit block write from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20);
for (i=0; i<(0x20/4); i++) {
data4_out[i] = data4_in[i] = ((4*i+3)<<24) | ((4*i+2)<<16) | ((4*i+1)<<8) | (4*i);
//printf("data_out = %0x\n", data4_out[i]);
}
//printf("Press a key for write\n"); getchar();
CHECK(dbg_wb_write_block32(SDRAM_BASE, &data4_out[0], 0x20));
 
// 32-bit block read is used for checking
printf("32-bit block read from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20);
CHECK(dbg_wb_read_block32(SDRAM_BASE, &data4_out[0], 0x20));
for (i=0; i<(0x20/4); i++) {
//printf("0x%x: 0x%x\n", SDRAM_BASE+(i*4), data_out[i]);
if (data4_in[i] != data4_out[i]) {
printf("SDRAM data differs. Expected: 0x%0x, read: 0x%0x\n", data4_in[i], data4_out[i]);
exit(1);
}
}
 
printf("16-bit block write from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20);
for (i=0; i<(0x20/2); i++) {
data2_out[i] = data2_in[i] = ((4*i+1)<<8) | (4*i);
//printf("data_out = %0x\n", data_out[i]);
}
CHECK(dbg_wb_write_block16(SDRAM_BASE, &data2_out[0], 0x20));
 
// 16-bit block read is used for checking
printf("16-bit block read from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20);
CHECK(dbg_wb_read_block16(SDRAM_BASE, &data2_out[0], 0x20));
for (i=0; i<(0x20/2); i++) {
//printf("0x%x: 0x%x\n", SDRAM_BASE+(i*4), data_out[i]);
if (data2_in[i] != data2_out[i]) {
printf("SDRAM data differs. Expected: 0x%0x, read: 0x%0x\n", data2_in[i], data2_out[i]);
exit(1);
}
}
 
printf("8-bit block write from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20);
for (i=0; i<(0x20/1); i++) {
data1_out[i] = data1_in[i] = (4*i);
//printf("data_out = %0x\n", data_out[i]);
}
CHECK(dbg_wb_write_block8(SDRAM_BASE, &data1_out[0], 0x20));
 
// 32-bit block read is used for checking
printf("8-bit block read from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20);
CHECK(dbg_wb_read_block8(SDRAM_BASE, &data1_out[0], 0x20));
for (i=0; i<(0x20/1); i++) {
//printf("0x%x: 0x%x\n", SDRAM_BASE+(i*4), data_out[i]);
if (data1_in[i] != data1_out[i]) {
printf("SDRAM data differs. Expected: 0x%0x, read: 0x%0x\n", data1_in[i], data1_out[i]);
exit(1);
}
}
}
 
 
void dbg_test() {
int i;
unsigned long npc, ppc, r1, insn, result;
unsigned char stalled;
#if 1
#define MC_BASE_ADDR 0x93000000
#define FLASH_BASE_ADDR 0xf0000000
#define FLASH_BAR_VAL FLASH_BASE_ADDR
#define FLASH_AMR_VAL 0xf0000000
#define FLASH_WTR_VAL 0x00011009
#define FLASH_RTR_VAL 0x01002009
#define SDRAM_BASE_ADDR 0x00000000
#define SDRAM_BAR_VAL SDRAM_BASE_ADDR
//#define SDRAM_SIZE 0x04000000 defined at the start of this program
#define SDRAM_AMR_VAL (~(SDRAM_SIZE -1))
#define SDRAM_RATR_VAL 0x00000006
#define SDRAM_RCDR_VAL 0x00000002
#define SDRAM_RCTR_VAL 0x00000006
#define SDRAM_REFCTR_VAL 0x00000006
#define SDRAM_PTR_VAL 0x00000001
#define SDRAM_RRDR_VAL 0x00000000
#define SDRAM_RIR_VAL 0x000000C0
 
#define MC_BAR_0 0x00
#define MC_AMR_0 0x04
#define MC_WTR_0 0x30
#define MC_RTR_0 0x34
#define MC_OSR 0xe8
#define MC_BAR_1 0x08
#define MC_BAR_4 0x80
#define MC_AMR_1 0x0c
#define MC_AMR_4 0x84
#define MC_CCR_1 0x24
#define MC_CCR_4 0xa0
#define MC_RATR 0xb0
#define MC_RCDR 0xc8
#define MC_RCTR 0xb4
#define MC_REFCTR 0xc4
#define MC_PTR 0xbc
#define MC_RRDR 0xb8
#define MC_RIR 0xcc
#define MC_ORR 0xe4
//usleep(1000000);
 
printf("Stall 8051\n");
CHECK(dbg_cpu1_write_reg(0, 0x01)); // stall 8051
 
printf("Stall or1k\n");
CHECK(dbg_cpu0_write_ctrl(0, 0x01)); // stall or1k
 
CHECK(dbg_cpu1_read_ctrl(0, &stalled));
if (!(stalled & 0x1)) {
printf("8051 should be stalled\n"); // check stall 8051
exit(1);
}
 
CHECK(dbg_cpu0_read_ctrl(0, &stalled));
if (!(stalled & 0x1)) {
printf("or1k should be stalled\n"); // check stall or1k
exit(1);
}
 
printf("Initialize Memory Controller\n");
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_BAR_0, FLASH_BAR_VAL & 0xffff0000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_AMR_0, FLASH_AMR_VAL & 0xffff0000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_WTR_0, FLASH_WTR_VAL));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RTR_0, FLASH_RTR_VAL));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x40000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_BAR_4, SDRAM_BAR_VAL & 0xffff0000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_AMR_4, SDRAM_AMR_VAL & 0xffff0000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_CCR_4, 0x00bf0005));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RATR, SDRAM_RATR_VAL));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RCDR, SDRAM_RCDR_VAL));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RCTR, SDRAM_RCTR_VAL));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_REFCTR, SDRAM_REFCTR_VAL));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_PTR, SDRAM_PTR_VAL));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RRDR, SDRAM_RRDR_VAL));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RIR, SDRAM_RIR_VAL));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x5e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x5e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x6e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x7e000033));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x7e000033));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_CCR_4, 0xc0bf0005));
CHECK(dbg_wb_read32(MC_BASE_ADDR+MC_CCR_4, &insn));
printf("expected %x, read %x\n", 0xc0bf0005, insn);
 
// SRAM initialized to 0x40000000
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_BAR_1, SRAM_BASE & 0xffff0000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_AMR_1, ~(SRAM_SIZE - 1) & 0xffff0000));
CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_CCR_1, 0xc020001f));
#endif
 
#if 1
#define CPU_OP_ADR 0
#define CPU_SEL_ADR 1
 
/* unstall the or1200 in highland_sys */
printf("Unstall or1k\n");
CHECK(dbg_wb_write32(0xb8070000, 2));
 
CHECK(dbg_cpu1_read_ctrl(0, &stalled));
if (!(stalled & 0x1)) {
printf("8051 should be stalled\n"); // check stall 8051
exit(1);
}
 
printf("Stall or1k\n");
CHECK(dbg_cpu0_write_ctrl(0, 0x01)); // stall or1k
 
printf("SDRAM test: \n");
CHECK(dbg_wb_write32(SDRAM_BASE+0x00, 0x12345678));
CHECK(dbg_wb_read32(SDRAM_BASE+0x00, &insn));
printf("expected %x, read %x\n", 0x12345678, insn);
if (insn != 0x12345678) exit(1);
CHECK(dbg_wb_write32(SDRAM_BASE+0x0000, 0x11112222));
CHECK(dbg_wb_read32(SDRAM_BASE+0x0000, &insn));
printf("expected %x, read %x\n", 0x11112222, insn);
if (insn != 0x11112222) exit(1);
 
CHECK(dbg_wb_write32(SDRAM_BASE+0x0004, 0x33334444));
CHECK(dbg_wb_write32(SDRAM_BASE+0x0008, 0x55556666));
CHECK(dbg_wb_write32(SDRAM_BASE+0x000c, 0x77778888));
CHECK(dbg_wb_write32(SDRAM_BASE+0x0010, 0x9999aaaa));
CHECK(dbg_wb_write32(SDRAM_BASE+0x0014, 0xbbbbcccc));
CHECK(dbg_wb_write32(SDRAM_BASE+0x0018, 0xddddeeee));
CHECK(dbg_wb_write32(SDRAM_BASE+0x001c, 0xffff0000));
CHECK(dbg_wb_write32(SDRAM_BASE+0x0020, 0xdeadbeef));
CHECK(dbg_wb_read32(SDRAM_BASE+0x0000, &insn));
printf("expected %x, read %x\n", 0x11112222, insn);
CHECK(dbg_wb_read32(SDRAM_BASE+0x0004, &insn));
printf("expected %x, read %x\n", 0x33334444, insn);
CHECK(dbg_wb_read32(SDRAM_BASE+0x0008, &insn));
printf("expected %x, read %x\n", 0x55556666, insn);
CHECK(dbg_wb_read32(SDRAM_BASE+0x000c, &insn));
printf("expected %x, read %x\n", 0x77778888, insn);
CHECK(dbg_wb_read32(SDRAM_BASE+0x0010, &insn));
printf("expected %x, read %x\n", 0x9999aaaa, insn);
CHECK(dbg_wb_read32(SDRAM_BASE+0x0014, &insn));
printf("expected %x, read %x\n", 0xbbbbcccc, insn);
CHECK(dbg_wb_read32(SDRAM_BASE+0x0018, &insn));
printf("expected %x, read %x\n", 0xddddeeee, insn);
CHECK(dbg_wb_read32(SDRAM_BASE+0x001c, &insn));
printf("expected %x, read %x\n", 0xffff0000, insn);
CHECK(dbg_wb_read32(SDRAM_BASE+0x0020, &insn));
printf("expected %x, read %x\n", 0xdeadbeef, insn);
if (insn != 0xdeadbeef) {
printf("SDRAM test failed !!!\n");
exit(1);
}
else
printf("SDRAM test passed\n");
 
printf("SRAM test: \n");
CHECK(dbg_wb_write32(SRAM_BASE+0x0000, 0x11112222));
CHECK(dbg_wb_write32(SRAM_BASE+0x0004, 0x33334444));
CHECK(dbg_wb_write32(SRAM_BASE+0x0008, 0x55556666));
CHECK(dbg_wb_write32(SRAM_BASE+0x000c, 0x77778888));
CHECK(dbg_wb_write32(SRAM_BASE+0x0010, 0x9999aaaa));
CHECK(dbg_wb_write32(SRAM_BASE+0x0014, 0xbbbbcccc));
CHECK(dbg_wb_write32(SRAM_BASE+0x0018, 0xddddeeee));
CHECK(dbg_wb_write32(SRAM_BASE+0x001c, 0xffff0000));
CHECK(dbg_wb_write32(SRAM_BASE+0x0020, 0xdedababa));
CHECK(dbg_wb_read32(SRAM_BASE+0x0000, &insn));
printf("expected %x, read %x\n", 0x11112222, insn);
CHECK(dbg_wb_read32(SRAM_BASE+0x0004, &insn));
printf("expected %x, read %x\n", 0x33334444, insn);
CHECK(dbg_wb_read32(SRAM_BASE+0x0008, &insn));
printf("expected %x, read %x\n", 0x55556666, insn);
CHECK(dbg_wb_read32(SRAM_BASE+0x000c, &insn));
printf("expected %x, read %x\n", 0x77778888, insn);
CHECK(dbg_wb_read32(SRAM_BASE+0x0010, &insn));
printf("expected %x, read %x\n", 0x9999aaaa, insn);
CHECK(dbg_wb_read32(SRAM_BASE+0x0014, &insn));
printf("expected %x, read %x\n", 0xbbbbcccc, insn);
CHECK(dbg_wb_read32(SRAM_BASE+0x0018, &insn));
printf("expected %x, read %x\n", 0xddddeeee, insn);
CHECK(dbg_wb_read32(SRAM_BASE+0x001c, &insn));
printf("expected %x, read %x\n", 0xffff0000, insn);
CHECK(dbg_wb_read32(SRAM_BASE+0x0020, &insn));
printf("expected %x, read %x\n", 0xdedababa, insn);
if (insn != 0xdedababa) {
printf("SRAN test failed!!!\n");
exit(1);
}
else
printf("SRAM test passed\n");
 
#if 1
test_sdram();
#endif
 
CHECK(dbg_wb_write32(SDRAM_BASE+0x00, 0xe0000005)); /* l.xor r0,r0,r0 */
CHECK(dbg_wb_write32(SDRAM_BASE+0x04, 0x9c200000)); /* l.addi r1,r0,0x0 */
CHECK(dbg_wb_write32(SDRAM_BASE+0x08, 0x18400000)); /* l.movhi r2,0x4000 */
CHECK(dbg_wb_write32(SDRAM_BASE+0x0c, 0xa8420030)); /* l.ori r2,r2,0x30 */
CHECK(dbg_wb_write32(SDRAM_BASE+0x10, 0x9c210001)); /* l.addi r1,r1,1 */
CHECK(dbg_wb_write32(SDRAM_BASE+0x14, 0x9c210001)); /* l.addi r1,r1,1 */
CHECK(dbg_wb_write32(SDRAM_BASE+0x18, 0xd4020800)); /* l.sw 0(r2),r1 */
CHECK(dbg_wb_write32(SDRAM_BASE+0x1c, 0x9c210001)); /* l.addi r1,r1,1 */
CHECK(dbg_wb_write32(SDRAM_BASE+0x20, 0x84620000)); /* l.lwz r3,0(r2) */
CHECK(dbg_wb_write32(SDRAM_BASE+0x24, 0x03fffffb)); /* l.j loop2 */
CHECK(dbg_wb_write32(SDRAM_BASE+0x28, 0xe0211800)); /* l.add r1,r1,r3 */
 
CHECK(dbg_cpu0_write((0 << 11) + 17, 0x01)); /* Enable exceptions */
CHECK(dbg_cpu0_write((6 << 11) + 20, 0x2000)); /* Trap causes stall */
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE)); /* Set PC */
CHECK(dbg_cpu0_write((6 << 11) + 16, 1 << 22)); /* Set step bit */
for(i = 0; i < 11; i++) {
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* 11x Unstall */
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1));
}
 
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1);
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000010, 0x00000028, 5);
result = npc + ppc + r1;
 
CHECK(dbg_cpu0_write((6 << 11) + 16, 0)); /* Reset step bit */
CHECK(dbg_wb_read32(SDRAM_BASE + 0x28, &insn)); /* Set trap insn in delay slot */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x28, 0x21000001));
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1));
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x28, insn)); /* Set back original insn */
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1);
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000010, 0x00000028, 8);
result = npc + ppc + r1 + result;
 
CHECK(dbg_wb_read32(SDRAM_BASE + 0x24, &insn)); /* Set trap insn in place of branch insn */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x24, 0x21000001));
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x10)); /* Set PC */
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1));
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x24, insn)); /* Set back original insn */
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1);
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000028, 0x00000024, 11);
result = npc + ppc + r1 + result;
 
CHECK(dbg_wb_read32(SDRAM_BASE + 0x20, &insn)); /* Set trap insn before branch insn */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, 0x21000001));
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x24)); /* Set PC */
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1));
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, insn)); /* Set back original insn */
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1);
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000024, 0x00000020, 24);
result = npc + ppc + r1 + result;
 
CHECK(dbg_wb_read32(SDRAM_BASE + 0x1c, &insn)); /* Set trap insn behind lsu insn */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x1c, 0x21000001));
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x20)); /* Set PC */
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1));
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x1c, insn)); /* Set back original insn */
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1);
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000020, 0x0000001c, 49);
result = npc + ppc + r1 + result;
 
CHECK(dbg_wb_read32(SDRAM_BASE + 0x20, &insn)); /* Set trap insn very near previous one */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, 0x21000001));
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x1c)); /* Set PC */
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1));
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, insn)); /* Set back original insn */
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1);
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000024, 0x00000020, 50);
result = npc + ppc + r1 + result;
 
CHECK(dbg_wb_read32(SDRAM_BASE + 0x10, &insn)); /* Set trap insn to the start */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x10, 0x21000001));
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x20) /* Set PC */);
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1));
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */
CHECK(dbg_wb_write32(SDRAM_BASE + 0x10, insn)); /* Set back original insn */
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1);
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000014, 0x00000010, 99);
result = npc + ppc + r1 + result;
 
CHECK(dbg_cpu0_write((6 << 11) + 16, 1 << 22)); /* Set step bit */
for(i = 0; i < 5; i++) {
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1));
}
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1);
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000028, 0x00000024, 101);
result = npc + ppc + r1 + result;
 
CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x24)); /* Set PC */
for(i = 0; i < 2; i++) {
CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */
do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1));
}
CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */
CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */
CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */
printf("Read npc = %.8lx ppc = %.8lx r1 = %.8lx\n", npc, ppc, r1);
printf("Expected npc = %.8lx ppc = %.8lx r1 = %.8lx\n", 0x00000010, 0x00000028, 201);
result = npc + ppc + r1 + result;
printf("result = %.8lx\n", result ^ 0xdeaddae1);
 
 
{ // 8051 TEST
unsigned long npc[3], tmp;
 
// WRITE ACC
CHECK(dbg_cpu1_write(0x20e0, 0xa6));
 
// READ ACC
CHECK(dbg_cpu1_read(0x20e0, &tmp)); // select SFR space
printf("Read 8051 ACC = %0x (expected a6)\n", tmp);
result = result + tmp;
 
// set exception to single step to jump over a loop
CHECK(dbg_cpu1_write(0x3010, 0xa0)); // set single step and global enable in EER
CHECK(dbg_cpu1_write(0x3011, 0x40)); // set evec = 24'h000040
CHECK(dbg_cpu1_write(0x3012, 0x00)); // (already reset value)
CHECK(dbg_cpu1_write(0x3013, 0x00)); // (already reset value)
 
// set HW breakpoint at PC == 0x41
CHECK(dbg_cpu1_write(0x3020, 0x41)); // DVR0 = 24'h000041
CHECK(dbg_cpu1_write(0x3023, 0x39)); // DCR0 = valid, == PC
CHECK(dbg_cpu1_write(0x3001, 0x04)); // DSR = watchpoint
 
// flush 8051 instruction cache
CHECK(dbg_cpu1_write(0x209f, 0x00));
 
// Put some instructions in ram (8-bit mode on wishbone)
CHECK(dbg_wb_write8 (0x40, 0x04)); // inc a
CHECK(dbg_wb_write8 (0x41, 0x03)); // rr a;
CHECK(dbg_wb_write8 (0x42, 0x14)); // dec a;
CHECK(dbg_wb_write8 (0x43, 0xf5)); // mov 0e5h, a;
CHECK(dbg_wb_write8 (0x44, 0xe5));
 
// unstall just 8051
CHECK(dbg_cpu1_write_reg(0, 0));
 
// read PC
CHECK(dbg_cpu1_read(0, &npc[0]));
CHECK(dbg_cpu1_read(1, &npc[1]));
CHECK(dbg_cpu1_read(2, &npc[2]));
printf("Read 8051 npc = %02x%02x%02x (expected 41)\n", npc[2], npc[1], npc[0]);
result = result + (npc[2] << 16) + (npc[1] << 8) + npc[0];
 
// READ ACC
CHECK(dbg_cpu1_read(0x20e0, &tmp)); // select SFR space
printf("Read 8051 ACC = %0x (expected a7)\n", tmp);
result = result + tmp;
 
// set sigle step to stop execution
CHECK(dbg_cpu1_write(0x3001, 0x20)); // set single step and global enable in DSR
 
// clear DRR
CHECK(dbg_cpu1_write(0x3000, 0x00)); // set single step and global enable in DRR
 
// unstall just 8051
CHECK(dbg_cpu1_write_reg(0, 0));
 
// read PC
CHECK(dbg_cpu1_read(0, &npc[0]));
CHECK(dbg_cpu1_read(1, &npc[1]));
CHECK(dbg_cpu1_read(2, &npc[2]));
printf("Read 8051 npc = %02x%02x%02x (expected 42)\n", npc[2], npc[1], npc[0]);
result = result + (npc[2] << 16) + (npc[1] << 8) + npc[0];
 
// READ ACC
CHECK(dbg_cpu1_read(0x20e0, &tmp)); // select SFR space
printf("Read 8051 ACC = %0x (expected d3)\n", tmp);
result = result + tmp;
 
printf("report (%x)\n", result ^ 0x6c1 ^ 0xdeaddead);
}
#endif
}
 
int main(int argc, char *argv[]) {
char *redirstr;
int trace_fd = 0;
char *s;
int err = DBG_ERR_OK;
 
int c;
const char *args;
char *port;
char *cable;
 
srand(getpid());
if ((argc < 3) || (argv[1][0] == '-') || (argv[2][0] == '-')) {
printf("JTAG protocol via parallel port for linux.\n");
printf("Copyright (C) 2001 Marko Mlinar, markom@opencores.org\n\n");
printf("Usage: %s [cable] [JTAG port_number]\n", argv[0]);
jp_print_cable_help();
return -1;
}
 
cable = argv[1];
port = argv[2];
 
if (!jp_select_cable(cable)) {
fprintf(stderr,"Error selecting cable %s\n", cable);
return -1;
}
 
/* Get the cable-arguments */
args = jp_get_cable_args();
 
/* Parse the cable arguments (if-any) */
for(;;) {
c = getopt(argc, argv, args);
if(c == -1)
break;
if(c == '?')
return 1;
if(!jp_cable_opt(c, optarg))
return 1;
}
if(!jp_init_cable())
return 1;
 
/* Initialize a new connection to the or1k board, and make sure we are
really connected. */
current_chain = -1;
if ((err = dbg_reset())) goto error;
 
/* Test the connection. */
/*dbg_test();*/
/* We have a connection. Establish server. */
serverPort = strtol(port,&s,10);
if(*s) return -1;
 
if(server_fd = GetServerSocket("or1ksim","tcp", serverPort)) {
printf("JTAG Proxy server started on port %d\n", serverPort);
printf("Press CTRL+c to exit.\n");
} else {
fprintf(stderr,"Cannot start JTAG Proxy server on port %d\n", serverPort);
exit(-1);
}
/* Do endless loop of checking and handle GDB requests. Ctrl-c exits. */
HandleServerSocket(true);
return 0;
error:
fprintf(stderr,"Connection with jtag via parallel port failed (err = %d).\n", err);
exit(-1);
}
 
/Makefile
0,0 → 1,31
prefix = /usr/local
 
CFLAGS = -g -O2
#CFLAGS = -g -O2 -DDEBUG2 -DDEBUG
CC = gcc
 
PROGRAMS = jp2
 
all: $(PROGRAMS)
 
.c.o:
$(CC) $(CFLAGS) -c $<
 
jp2: Makefile jp2.o gdb2.o jp2.h jp-io.o jp.h
rm -f $@
$(CC) -o $@ $(CFLAGS) jp2.o jp-io.o gdb2.o
 
jp-io-vpi.vpi: jp-io-vpi.c
iverilog-vpi jp-io-vpi.c
 
vpi: jp-io-vpi.vpi Makefile
 
install: all
[ -d $(prefix)/bin ] || mkdir -p $(prefix)/bin
for p in $(PROGRAMS) ; do \
/bin/rm -f $(prefix)/bin/$$p; \
/bin/cp -p $$p $(prefix)/bin/$$p; \
done
 
clean: Makefile
rm -f $(PROGRAMS) jp-io-vpi.vpi *.o *~
/README
0,0 → 1,64
JTAG PROGRAMMING UTILITY README FOR OPENRISC 1000
 
NOTE:
 
This is a modified version of JTAG utility to work with
Celoxica boards.
 
INTRODUCTION
 
JP1 is a proprietary JTAG protocol. It is very simple, and perhaps
its biggest advantage is that no special HW is needed -- only a
parallel port cable and some buffers. It is compatible with Xilinx
Parallel Cable III.
 
Gdb is capable of connecting, controlling and debugging the board
via JP1. Currently jp1 has support only for Linux.
 
 
 
USAGE
 
jp1 [cable] [port] <cable options>
 
The cable parameter selects the cable to use for communicateing with the board.
At the time of writting, cable may be one of xpc3, xess, rtl_sim or vpi. xpc3
assumes a xillinx parallel cable 3, rtl_sim connects to a rtl simulator,
communicateing with it via files (slow), vpi connects to a rtl simulator via the
vpi (faster). The port parameter specified designates TCP/IP port address where
the server starts. Run jp1 without arguments for a list of cable specific
options.
 
First, start the jp1 program in root mode, e.g.:
 
./jp1 xpc3 9999
 
Then start gdb and connect to it,
using e.g.:
 
$ or32-rtems-gdb test.or32
(gdb) target jtag jtag://localhost:9999
 
Then load the program into the memory:
 
(gdb) load
 
and start it up:
 
(gdb) set $pc=0x100
 
You can write stepi or si, to see if things are working
correctly:
 
(gdb) stepi
 
If the program counter increases, we can set the breakpoint
and run the program with command 'continue' or 'c'.
 
 
 
AUTHORS
 
Simons Srot, simons@opencores.org
Marko Mlinar, markom@opencores.org
 
/gdb.c
0,0 → 1,573
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
 
/* Libraries for JTAG proxy server. */
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <inttypes.h>
#include <errno.h>
 
#include "gdb.h" /* partially copied from gdb/config/or1k */
#include "jp2.h"
 
 
/* connection to jp2 routines */
int gdb_chain = -1;
 
int gdb_read_reg(unsigned long adr, unsigned long *data) {
switch (gdb_chain) {
SC_RISC_DEBUG: return dbg_cpu_read32(adr, data) ? ERR_CRC : ERR_NONE;
SC_REGISTER: return dbg_cpu_read_reg(adr, data) ? ERR_CRC : ERR_NONE;
SC_WISHBONE: return dbg_wb_read32(adr, data) ? ERR_CRC : ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_write_reg(unsigned long adr, unsigned long data) {
switch (gdb_chain) {
SC_RISC_DEBUG: return dbg_cpu_write32(adr, data) ? ERR_CRC : ERR_NONE;
SC_REGISTER: return dbg_cpu_write_reg(adr, data) ? ERR_CRC : ERR_NONE;
SC_WISHBONE: return dbg_wb_write32(adr, data) ? ERR_CRC : ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_read_block(unsigned long adr, unsigned long *data, int len) {
switch (gdb_chain) {
SC_WISHBONE: return dbg_wb_read_block32(adr, data, len) ? ERR_CRC : ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_write_block(unsigned long adr, unsigned long *data, int len) {
switch (gdb_chain) {
SC_WISHBONE: return dbg_wb_write_block32(adr, data, len) ? ERR_CRC : ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_set_chain(int chain) {
switch (gdb_chain) {
SC_RISC_DEBUG:
SC_REGISTER:
SC_WISHBONE: gdb_chain = chain;
return ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
}
 
 
 
/************************
JTAG Server Routines
************************/
 
unsigned int serverIP = 0;
unsigned int serverPort = 0;
unsigned int server_fd = 0;
unsigned int gdb_fd = 0;
static int gdb_read(void*, int);
static int gdb_write(void*, int);
static void ProtocolClean(int, int32_t);
 
static int tcp_level = 0;
 
/* Added by CZ 24/05/01 */
int GetServerSocket(const char* name, const char* proto, int port) {
struct servent *service;
struct protoent *protocol;
struct sockaddr_in sa;
struct hostent *hp;
int sockfd;
char myname[256];
int flags;
char sTemp[256];
 
/* First, get the protocol number of TCP */
if (!(protocol = getprotobyname(proto))) {
sprintf(sTemp, "Unable to load protocol \"%s\"", proto);
perror(sTemp);
return 0;
}
tcp_level = protocol->p_proto; /* Save for later */
 
/* If we weren't passed a non standard port, get the port
from the services directory. */
if (!port && (service = getservbyname(name, protocol->p_name)))
port = ntohs(service->s_port);
/* Create the socket using the TCP protocol */
if ((sockfd = socket(PF_INET, SOCK_STREAM, protocol->p_proto)) < 0) {
perror("Unable to create socket");
return 0;
}
flags = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&flags, sizeof(int)) < 0) {
sprintf(sTemp, "Can not set SO_REUSEADDR option on socket %d", sockfd);
perror(sTemp);
close(sockfd);
return 0;
}
 
/* The server should also be non blocking. Get the current flags. */
if((flags = fcntl(sockfd, F_GETFL, 0)) < 0) {
sprintf(sTemp, "Unable to get flags for socket %d", sockfd);
perror(sTemp);
close(sockfd);
return 0;
}
 
/* Set the nonblocking flag */
if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
sprintf(sTemp, "Unable to set flags for socket %d to value 0x%08x",
sockfd, flags | O_NONBLOCK);
perror(sTemp);
close(sockfd);
return 0;
}
 
/* Find out what our address is */
memset(&sa, 0, sizeof(struct sockaddr_in));
gethostname(myname, sizeof(myname));
if(!(hp = gethostbyname(myname))) {
perror("Unable to read hostname");
close(sockfd);
return 0;
}
/* Bind our socket to the appropriate address */
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons(port);
if(bind(sockfd, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)) < 0) {
sprintf(sTemp, "Unable to bind socket %d to port %d", sockfd, port);
perror(sTemp);
close(sockfd);
return 0;
}
serverIP = sa.sin_addr.s_addr;
flags = sizeof(struct sockaddr_in);
if(getsockname(sockfd, (struct sockaddr*)&sa, &flags) < 0) {
sprintf(sTemp, "Unable to get socket information for socket %d", sockfd);
perror(sTemp);
close(sockfd);
return 0;
}
serverPort = ntohs(sa.sin_port);
 
/* Set the backlog to 1 connections */
if(listen(sockfd, 1) < 0) {
sprintf(sTemp, "Unable to set backlog on socket %d to %d", sockfd, 1);
perror(sTemp);
close(sockfd);
return 0;
}
 
return sockfd;
}
 
void HandleServerSocket(Boolean block) {
struct pollfd fds[2];
int n;
rebuild:
n = 0;
if(!server_fd && !gdb_fd) return;
 
if(server_fd) {
fds[n].fd = server_fd;
fds[n].events = POLLIN;
fds[n++].revents = 0;
}
if(gdb_fd) {
fds[n].fd = gdb_fd;
fds[n].events = POLLIN;
fds[n++].revents = 0;
}
 
while(1) {
switch(poll(fds, n, -1)) {
case 0:
case -1:
if(errno == EINTR) continue;
perror("poll");
server_fd = 0;
return;
default:
/* Make sure to handle the gdb port first! */
if (gdb_fd && (fds[0].revents && !server_fd || fds[1].revents && server_fd)) {
int revents = server_fd ? fds[1].revents : fds[0].revents;
if (revents & POLLIN) GDBRequest();
else {/* Error Occurred */
fprintf(stderr, "Received flags 0x%08x on gdb socket. Shutting down.\n", revents);
close(gdb_fd);
gdb_fd = 0;
}
}
if(fds[0].revents && server_fd) {
if(fds[0].revents & POLLIN) {
JTAGRequest();
goto rebuild;
} else { /* Error Occurred */
fprintf(stderr, "Received flags 0x%08x on server. Shutting down.\n", fds[0].revents);
close(server_fd);
server_fd = 0;
serverPort = 0;
serverIP = 0;
return;
}
}
break;
} /* End of switch statement */
} /* End of while statement */
}
 
void JTAGRequest() {
struct sockaddr_in sa;
struct sockaddr* addr = (struct sockaddr*)&sa;
int n = sizeof(struct sockaddr_in);
int fd = accept(server_fd, addr, &n);
int on_off = 0; /* Turn off Nagel's algorithm on the socket */
int flags;
char sTemp[256];
 
if(fd < 0) {
/* This is valid, because a connection could have started,
and then terminated due to a protocol error or user
initiation before the accept could take place. */
if(errno != EWOULDBLOCK && errno != EAGAIN) {
perror("accept");
close(server_fd);
server_fd = 0;
serverPort = 0;
serverIP = 0;
}
return;
}
 
if(gdb_fd) {
close(fd);
return;
}
 
if((flags = fcntl(fd, F_GETFL,0)) < 0) {
sprintf(sTemp, "Unable to get flags for gdb socket %d", fd);
perror(sTemp);
close(fd);
return;
}
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
sprintf(sTemp, "Unable to set flags for gdb socket %d to value 0x%08x",
fd, flags | O_NONBLOCK);
perror(sTemp);
close(fd);
return;
}
 
if(setsockopt(fd, tcp_level, TCP_NODELAY, &on_off, sizeof(int)) < 0) {
sprintf(sTemp, "Unable to disable Nagel's algorithm for socket %d.\nsetsockopt", fd);
perror(sTemp);
close(fd);
return;
}
 
gdb_fd = fd;
}
 
void GDBRequest() {
JTAGProxyWriteMessage msg_write;
JTAGProxyReadMessage msg_read;
JTAGProxyChainMessage msg_chain;
JTAGProxyWriteResponse resp_write;
JTAGProxyReadResponse resp_read;
JTAGProxyChainResponse resp_chain;
JTAGProxyBlockWriteMessage *msg_bwrite;
JTAGProxyBlockReadMessage msg_bread;
JTAGProxyBlockWriteResponse resp_bwrite;
JTAGProxyBlockReadResponse *resp_bread;
char *buf;
unsigned long long data;
uint32_t command, length;
int len, i;
int err = 0;
 
/* First, we must read the incomming command */
if(gdb_read(&command, sizeof(uint32_t)) < 0) {
if(gdb_fd) {
perror("gdb socket - 1");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
if(gdb_read(&length, sizeof(uint32_t)) < 0) {
if(gdb_fd) {
perror("gdb socket - 2");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
length = ntohl(length);
 
/* Now, verify the protocol and implement the command */
switch(ntohl(command)) {
case JTAG_COMMAND_WRITE:
if(length != sizeof(msg_write) - 8) {
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR);
return;
}
buf = (char*)&msg_write;
if(gdb_read(&buf[8], length) < 0) {
if(gdb_fd) {
perror("gdb socket - 3");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
msg_write.address = ntohl(msg_write.address);
msg_write.data_H = ntohl(msg_write.data_H);
msg_write.data_L = ntohl(msg_write.data_L);
err = gdb_write_reg(msg_write.address, msg_write.data_L);
resp_write.status = htonl(err);
if(gdb_write(&resp_write, sizeof(resp_write)) < 0) {
if(gdb_fd) {
perror("gdb socket - 4");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
break;
case JTAG_COMMAND_READ:
if(length != sizeof(msg_read) - 8) {
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR);
return;
}
buf = (char*)&msg_read;
if(gdb_read(&buf[8], length) < 0) {
if(gdb_fd) {
perror("gdb socket - 5");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
msg_read.address = ntohl(msg_read.address);
err = gdb_read_reg(msg_read.address, (unsigned long *)&resp_read.data_L);
resp_read.status = htonl(err);
resp_read.data_H = 0;
resp_read.data_L = htonl(resp_read.data_L);
if(gdb_write(&resp_read, sizeof(resp_read)) < 0) {
if(gdb_fd) {
perror("gdb socket - 6");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
break;
case JTAG_COMMAND_BLOCK_WRITE:
if(length < sizeof(JTAGProxyBlockWriteMessage)-8) {
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR);
return;
}
if(!(buf = (char*)malloc(8+length))) {
ProtocolClean(length, JTAG_PROXY_OUT_OF_MEMORY);
return;
}
msg_bwrite = (JTAGProxyBlockWriteMessage*)buf;
if(gdb_read(&buf[8], length) < 0) {
if(gdb_fd) {
perror("gdb socket - 5");
close(gdb_fd);
gdb_fd = 0;
}
free(buf);
return;
}
msg_bwrite->address = ntohl(msg_bwrite->address);
msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters);
for(i=0;i<msg_bwrite->nRegisters;i++) {
msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]);
}
err = gdb_write_block(msg_bwrite->address, (unsigned long*)msg_bwrite->data, msg_bwrite->nRegisters * 4);
resp_bwrite.status = htonl(err);
free(buf);
msg_bwrite = (JTAGProxyBlockWriteMessage *)NULL;
buf = (char *)msg_bwrite;
if(gdb_write(&resp_bwrite, sizeof(resp_bwrite)) < 0) {
if(gdb_fd) {
perror("gdb socket - 4");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
break;
case JTAG_COMMAND_BLOCK_READ:
if(length != sizeof(msg_bread) - 8) {
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR);
return;
}
buf = (char*)&msg_bread;
if(gdb_read(&buf[8], length) < 0) {
if(gdb_fd) {
perror("gdb socket - 5");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
msg_bread.address = ntohl(msg_bread.address);
msg_bread.nRegisters = ntohl(msg_bread.nRegisters);
len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1);
if(!(buf = (char*)malloc(len))) {
ProtocolClean(0, JTAG_PROXY_OUT_OF_MEMORY);
return;
}
resp_bread = (JTAGProxyBlockReadResponse*)buf;
err = gdb_read_block(msg_bread.address, (unsigned long*)resp_bread->data, msg_bread.nRegisters * 4);
for(i=0;i<msg_bread.nRegisters;i++) {
/* Read previous, address next one. */
resp_bread->data[i] = htonl(resp_bread->data[i]);
}
resp_bread->status = htonl(err);
resp_bread->nRegisters = htonl(msg_bread.nRegisters);
if(gdb_write(resp_bread, len) < 0) {
if(gdb_fd) {
perror("gdb socket - 6");
close(gdb_fd);
gdb_fd = 0;
}
free(buf);
return;
}
free(buf);
resp_bread = (JTAGProxyBlockReadResponse *)NULL;
buf = (char *)resp_bread;
break;
case JTAG_COMMAND_CHAIN:
if(length != sizeof(msg_chain) - 8) {
ProtocolClean(length, JTAG_PROXY_PROTOCOL_ERROR);
return;
}
buf = (char*)&msg_chain;
if(gdb_read(&buf[8], sizeof(msg_chain)-8) < 0) {
if(gdb_fd) {
perror("gdb socket - 7");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
msg_chain.chain = htonl(msg_chain.chain);
err = gdb_set_chain(msg_chain.chain);
resp_chain.status = htonl(err);
if(gdb_write(&resp_chain, sizeof(resp_chain)) < 0) {
if(gdb_fd) {
perror("gdb socket - 8");
close(gdb_fd);
gdb_fd = 0;
}
return;
}
break;
default:
perror("Unknown JTAG command.");
ProtocolClean(length, JTAG_PROXY_COMMAND_NOT_IMPLEMENTED);
break;
}
}
 
static void ProtocolClean(int length, int32_t err) {
char buf[4096];
 
err = htonl(err);
if((gdb_read(buf, length) < 0) || (gdb_write(&err, sizeof(err)) < 0) && gdb_fd) {
perror("gdb socket - 9");
close(gdb_fd);
gdb_fd = 0;
}
}
 
static int gdb_write(void* buf, int len) {
int n;
char* w_buf = (char*)buf;
struct pollfd block;
 
while(len) {
if((n = write(gdb_fd, w_buf, len)) < 0) {
switch(errno) {
case EWOULDBLOCK: /* or EAGAIN */
/* We've been called on a descriptor marked
for nonblocking I/O. We better simulate
blocking behavior. */
block.fd = gdb_fd;
block.events = POLLOUT;
block.revents = 0;
poll(&block, 1, -1);
continue;
case EINTR:
continue;
case EPIPE:
close(gdb_fd);
gdb_fd = 0;
return -1;
default:
return -1;
}
} else {
len -= n;
w_buf += n;
}
}
return 0;
}
 
static int gdb_read(void* buf, int len) {
int n;
char* r_buf = (char*)buf;
struct pollfd block;
 
while(len) {
if((n = read(gdb_fd, r_buf, len)) < 0) {
switch(errno) {
case EWOULDBLOCK: /* or EAGAIN */
/* We've been called on a descriptor marked
for nonblocking I/O. We better simulate
blocking behavior. */
block.fd = gdb_fd;
block.events = POLLIN;
block.revents = 0;
poll(&block, 1, -1);
continue;
case EINTR:
continue;
default:
return -1;
}
} else if(n == 0) {
close(gdb_fd);
gdb_fd = 0;
return -1;
} else {
len -= n;
r_buf += n;
}
}
return 0;
}

powered by: WebSVN 2.1.0

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