URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rc203soc/] [sw/] [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; }