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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [jtag/] [jp-io.c] - Rev 1765

Compare with Previous | Blame | View Log

/* jp-io.c -- Low level JTAG communications
   Copyright (C) 2001 Marko Mlinar, markom@opencores.org
   Copyright (C) 2004 György Jeney, nog@sdf.lonestar.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;
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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