From e9297b40b994f071474210e7d9e224d50e25fcaf Mon Sep 17 00:00:00 2001 From: drath Date: Wed, 22 Nov 2006 13:03:10 +0000 Subject: - added a PLD (programmable logic device) subsystem for FPGA, CPLD etc. configuration - added support for loading .bit files into Xilinx Virtex-II devices - added support for the Gateworks GW16012 JTAG dongle - merged CFI fixes from XScale branch - a few minor fixes git-svn-id: svn://svn.berlios.de/openocd/trunk@116 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/jtag/Makefile.am | 8 +- src/jtag/ft2232.c | 309 ++++++++++++++++++++++++++++--- src/jtag/gw16012.c | 507 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/jtag/jtag.c | 17 +- 4 files changed, 807 insertions(+), 34 deletions(-) create mode 100644 src/jtag/gw16012.c (limited to 'src/jtag') diff --git a/src/jtag/Makefile.am b/src/jtag/Makefile.am index c63c734a..d4812a46 100644 --- a/src/jtag/Makefile.am +++ b/src/jtag/Makefile.am @@ -55,6 +55,12 @@ else AT91RM9200FILES = endif -libjtag_a_SOURCES = jtag.c $(BITBANGFILES) $(PARPORTFILES) $(FT2232FILES) $(AMTJTAGACCELFILES) $(EP93XXFILES) $(AT91RM9200FILES) +if GW16012 +GW16012FILES = gw16012.c +else +GW16012FILES = +endif + +libjtag_a_SOURCES = jtag.c $(BITBANGFILES) $(PARPORTFILES) $(FT2232FILES) $(AMTJTAGACCELFILES) $(EP93XXFILES) $(AT91RM9200FILES) $(GW16012FILES) noinst_HEADERS = bitbang.h jtag.h diff --git a/src/jtag/ft2232.c b/src/jtag/ft2232.c index 67167c78..096111bc 100644 --- a/src/jtag/ft2232.c +++ b/src/jtag/ft2232.c @@ -52,13 +52,13 @@ /* enable this to debug io latency */ -#if 0 +#if 1 #define _DEBUG_USB_IO_ #endif /* enable this to debug communication */ -#if 0 +#if 1 #define _DEBUG_USB_COMMS_ #endif @@ -470,7 +470,7 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size int cur_byte = 0; int last_bit; - if ((!ir_scan && (cur_state != TAP_SD)) || (ir_scan && (cur_state != TAP_SI))) + if (!((!ir_scan && (cur_state == TAP_SD)) || (ir_scan && (cur_state == TAP_SI)))) { /* command "Clock Data to TMS/CS Pin (no Read)" */ BUFFER_ADD = 0x4b; @@ -491,8 +491,9 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size } /* add command for complete bytes */ - if (num_bytes > 1) + while (num_bytes > 1) { + int thisrun_bytes; if (type == SCAN_IO) { /* Clock Data Bytes In and Out LSB First */ @@ -511,24 +512,206 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size BUFFER_ADD = 0x28; //DEBUG("added TDI bytes (i %i)", num_bytes); } - BUFFER_ADD = (num_bytes-2) & 0xff; - BUFFER_ADD = ((num_bytes-2) >> 8) & 0xff; + thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1); + num_bytes -= thisrun_bytes; + BUFFER_ADD = (thisrun_bytes - 1) & 0xff; + BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff; + if (type != SCAN_IN) + { + /* add complete bytes */ + while(thisrun_bytes-- > 0) + { + BUFFER_ADD = buffer[cur_byte]; + cur_byte++; + bits_left -= 8; + } + } + else /* (type == SCAN_IN) */ + { + bits_left -= 8 * (thisrun_bytes); + } } + + /* the most signifcant bit is scanned during TAP movement */ if (type != SCAN_IN) + last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1; + else + last_bit = 0; + + /* process remaining bits but the last one */ + if (bits_left > 1) { - /* add complete bytes */ - while(num_bytes-- > 1) + if (type == SCAN_IO) + { + /* Clock Data Bits In and Out LSB First */ + BUFFER_ADD = 0x3b; + //DEBUG("added TDI bits (io) %i", bits_left - 1); + } + else if (type == SCAN_OUT) { + /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ + BUFFER_ADD = 0x1b; + //DEBUG("added TDI bits (o)"); + } + else if (type == SCAN_IN) + { + /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ + BUFFER_ADD = 0x2a; + //DEBUG("added TDI bits (i %i)", bits_left - 1); + } + BUFFER_ADD = bits_left - 2; + if (type != SCAN_IN) BUFFER_ADD = buffer[cur_byte]; - cur_byte++; - bits_left -= 8; + } + + if ((ir_scan && (end_state == TAP_SI)) || + (!ir_scan && (end_state == TAP_SD))) + { + if (type == SCAN_IO) + { + /* Clock Data Bits In and Out LSB First */ + BUFFER_ADD = 0x3b; + //DEBUG("added TDI bits (io) %i", bits_left - 1); } + else if (type == SCAN_OUT) + { + /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ + BUFFER_ADD = 0x1b; + //DEBUG("added TDI bits (o)"); + } + else if (type == SCAN_IN) + { + /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ + BUFFER_ADD = 0x2a; + //DEBUG("added TDI bits (i %i)", bits_left - 1); + } + BUFFER_ADD = 0x0; + BUFFER_ADD = last_bit; } - if (type == SCAN_IN) + else + { + /* move from Shift-IR/DR to end state */ + if (type != SCAN_OUT) + { + /* Clock Data to TMS/CS Pin with Read */ + BUFFER_ADD = 0x6b; + //DEBUG("added TMS scan (read)"); + } + else + { + /* Clock Data to TMS/CS Pin (no Read) */ + BUFFER_ADD = 0x4b; + //DEBUG("added TMS scan (no read)"); + } + BUFFER_ADD = 0x6; + BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7); + cur_state = end_state; + } +} + +int ft2232_large_scan(scan_command_t *cmd, enum scan_type type, u8 *buffer, int scan_size) +{ + int num_bytes = (scan_size + 7) / 8; + int bits_left = scan_size; + int cur_byte = 0; + int last_bit; + u8 *receive_buffer = malloc(CEIL(scan_size, 8)); + u8 *receive_pointer = receive_buffer; + u32 bytes_written; + u32 bytes_read; + int retval; + int thisrun_read = 0; + + if (cmd->ir_scan) { - bits_left -= 8 * (num_bytes - 1); + ERROR("BUG: large IR scans are not supported"); + exit(-1); } + if (cur_state != TAP_SD) + { + /* command "Clock Data to TMS/CS Pin (no Read)" */ + BUFFER_ADD = 0x4b; + /* scan 7 bit */ + BUFFER_ADD = 0x6; + /* TMS data bits */ + BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD); + cur_state = TAP_SD; + } + + if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK) + { + ERROR("couldn't write MPSSE commands to FT2232"); + exit(-1); + } + DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written); + ft2232_buffer_size = 0; + + /* add command for complete bytes */ + while (num_bytes > 1) + { + int thisrun_bytes; + + if (type == SCAN_IO) + { + /* Clock Data Bytes In and Out LSB First */ + BUFFER_ADD = 0x39; + //DEBUG("added TDI bytes (io %i)", num_bytes); + } + else if (type == SCAN_OUT) + { + /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ + BUFFER_ADD = 0x19; + //DEBUG("added TDI bytes (o)"); + } + else if (type == SCAN_IN) + { + /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */ + BUFFER_ADD = 0x28; + //DEBUG("added TDI bytes (i %i)", num_bytes); + } + thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1); + thisrun_read = thisrun_bytes; + num_bytes -= thisrun_bytes; + BUFFER_ADD = (thisrun_bytes - 1) & 0xff; + BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff; + if (type != SCAN_IN) + { + /* add complete bytes */ + while(thisrun_bytes-- > 0) + { + BUFFER_ADD = buffer[cur_byte]; + cur_byte++; + bits_left -= 8; + } + } + else /* (type == SCAN_IN) */ + { + bits_left -= 8 * (thisrun_bytes); + } + + if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK) + { + ERROR("couldn't write MPSSE commands to FT2232"); + exit(-1); + } + DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written); + ft2232_buffer_size = 0; + + if (type != SCAN_OUT) + { + if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK) + { + ERROR("couldn't read from FT2232"); + exit(-1); + } + DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read); + receive_pointer += bytes_read; + } + } + + thisrun_read = 0; + /* the most signifcant bit is scanned during TAP movement */ if (type != SCAN_IN) last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1; @@ -559,30 +742,83 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size BUFFER_ADD = bits_left - 2; if (type != SCAN_IN) BUFFER_ADD = buffer[cur_byte]; + + if (type != SCAN_OUT) + thisrun_read += 2; } - /* move from Shift-IR/DR to end state */ - if (type != SCAN_OUT) + if (end_state == TAP_SD) { - /* Clock Data to TMS/CS Pin with Read */ - BUFFER_ADD = 0x6b; - //DEBUG("added TMS scan (read)"); + if (type == SCAN_IO) + { + /* Clock Data Bits In and Out LSB First */ + BUFFER_ADD = 0x3b; + //DEBUG("added TDI bits (io) %i", bits_left - 1); + } + else if (type == SCAN_OUT) + { + /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ + BUFFER_ADD = 0x1b; + //DEBUG("added TDI bits (o)"); + } + else if (type == SCAN_IN) + { + /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ + BUFFER_ADD = 0x2a; + //DEBUG("added TDI bits (i %i)", bits_left - 1); + } + BUFFER_ADD = 0x0; + BUFFER_ADD = last_bit; } else { - /* Clock Data to TMS/CS Pin (no Read) */ - BUFFER_ADD = 0x4b; - //DEBUG("added TMS scan (no read)"); + /* move from Shift-IR/DR to end state */ + if (type != SCAN_OUT) + { + /* Clock Data to TMS/CS Pin with Read */ + BUFFER_ADD = 0x6b; + //DEBUG("added TMS scan (read)"); + } + else + { + /* Clock Data to TMS/CS Pin (no Read) */ + BUFFER_ADD = 0x4b; + //DEBUG("added TMS scan (no read)"); + } + BUFFER_ADD = 0x6; + BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7); + cur_state = end_state; } - BUFFER_ADD = 0x6; - BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7); - cur_state = end_state; - + + if (type != SCAN_OUT) + thisrun_read += 1; + + if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK) + { + ERROR("couldn't write MPSSE commands to FT2232"); + exit(-1); + } + DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written); + ft2232_buffer_size = 0; + + if (type != SCAN_OUT) + { + if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK) + { + ERROR("couldn't read from FT2232"); + exit(-1); + } + DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read); + receive_pointer += bytes_read; + } + + return ERROR_OK; } int ft2232_predict_scan_out(int scan_size, enum scan_type type) { int predicted_size = 3; + int num_bytes = (scan_size - 1) / 8; if (cur_state != TAP_SD) predicted_size += 3; @@ -590,14 +826,14 @@ int ft2232_predict_scan_out(int scan_size, enum scan_type type) if (type == SCAN_IN) /* only from device to host */ { /* complete bytes */ - predicted_size += (CEIL(scan_size, 8) > 1) ? 3 : 0; + predicted_size += (CEIL(num_bytes, 65536)) * 3; /* remaining bits - 1 (up to 7) */ predicted_size += ((scan_size - 1) % 8) ? 2 : 0; } else /* host to device, or bidirectional */ { /* complete bytes */ - predicted_size += (CEIL(scan_size, 8) > 1) ? (CEIL(scan_size, 8) + 3 - 1) : 0; + predicted_size += num_bytes + (CEIL(num_bytes, 65536)) * 3; /* remaining bits -1 (up to 7) */ predicted_size += ((scan_size - 1) % 8) ? 3 : 0; } @@ -910,9 +1146,26 @@ int ft2232_execute_queue() scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); type = jtag_scan_type(cmd->cmd.scan); predicted_size = ft2232_predict_scan_out(scan_size, type); - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) + if ((predicted_size + 1) > FT2232_BUFFER_SIZE) + { + DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)"); + /* unsent commands before this */ + if (first_unsent != cmd) + ft2232_send_and_recv(first_unsent, cmd); + + /* current command */ + if (cmd->cmd.scan->end_state != -1) + ft2232_end_state(cmd->cmd.scan->end_state); + ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size); + require_send = 0; + first_unsent = cmd->next; + if (buffer) + free(buffer); + break; + } + else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - DEBUG("ftd2xx buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd); + DEBUG("ft2232 buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd); ft2232_send_and_recv(first_unsent, cmd); require_send = 0; first_unsent = cmd; diff --git a/src/jtag/gw16012.c b/src/jtag/gw16012.c new file mode 100644 index 00000000..6210a52c --- /dev/null +++ b/src/jtag/gw16012.c @@ -0,0 +1,507 @@ +/*************************************************************************** + * Copyright (C) 2006 by Dominic Rath * + * Dominic.Rath@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "replacements.h" + +#include "jtag.h" + +/* system includes */ + +/* system includes */ +// -ino: 060521-1036 +#ifdef __FreeBSD__ + +#include +#include +#include +#define ioperm(startport,length,enable)\ + i386_set_ioperm((startport), (length), (enable)) + +#else + +#ifndef _WIN32 +#include +#else +#include "errno.h" +#endif /* _WIN32 */ + +#endif /* __FreeBSD__ */ + +#include +#include + +#include +#include + +#if PARPORT_USE_PPDEV == 1 +#ifdef __FreeBSD__ +#include +#include +#define PPRSTATUS PPIGSTATUS +#define PPWDATA PPISDATA +#else +#include +#include +#endif +#include +#include +#endif + +#if PARPORT_USE_GIVEIO == 1 +#if IS_CYGWIN == 1 +#include +#include +#undef ERROR +#endif +#endif + +#include "log.h" + +/* configuration */ +unsigned long gw16012_port; + +/* interface variables + */ +static u8 gw16012_msb = 0x0; +static u8 gw16012_control_value = 0x0; + +#if PARPORT_USE_PPDEV == 1 +static int device_handle; +#endif + +int gw16012_execute_queue(void); +int gw16012_register_commands(struct command_context_s *cmd_ctx); +int gw16012_speed(int speed); +int gw16012_init(void); +int gw16012_quit(void); + +int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); + +jtag_interface_t gw16012_interface = +{ + .name = "gw16012", + + .execute_queue = gw16012_execute_queue, + + .support_pathmove = 0, + + .speed = gw16012_speed, + .register_commands = gw16012_register_commands, + .init = gw16012_init, + .quit = gw16012_quit, +}; + +int gw16012_register_commands(struct command_context_s *cmd_ctx) +{ + register_command(cmd_ctx, NULL, "parport_port", gw16012_handle_parport_port_command, + COMMAND_CONFIG, NULL); + + return ERROR_OK; +} + +void gw16012_data(u8 value) +{ + value = (value & 0x7f) | gw16012_msb; + gw16012_msb ^= 0x80; /* toggle MSB */ + + #if PARPORT_USE_PPDEV == 1 + ioctl(device_handle, PPWDATA, &value); + #else + #ifdef __FreeBSD__ + outb(gw16012_port, value); + #else + outb(value, gw16012_port); + #endif + #endif +} + +void gw16012_control(u8 value) +{ + if (value != gw16012_control_value) + { + gw16012_control_value = value; + + #if PARPORT_USE_PPDEV == 1 + ioctl(device_handle, PPWCONTROL, &gw16012_control_value); + #else + #ifdef __FreeBSD__ + outb(gw16012_port + 2, gw16012_control_value); + #else + outb(gw16012_control_value, gw16012_port + 2); + #endif + #endif + } +} + +void gw16012_input(u8 *value) +{ + #if PARPORT_USE_PPDEV == 1 + ioctl(device_handle, PPRSTATUS, value); + #else + *value = inb(gw16012_port + 1); + #endif +} + +/* (1) assert or (0) deassert reset lines */ +void gw16012_reset(int trst, int srst) +{ + DEBUG("trst: %i, srst: %i", trst, srst); + + if (trst == 0) + gw16012_control(0x0d); + else if (trst == 1) + gw16012_control(0x0c); + + if (srst == 0) + gw16012_control(0x0a); + else if (srst == 1) + gw16012_control(0x0b); +} + +int gw16012_speed(int speed) +{ + + return ERROR_OK; +} + +void gw16012_end_state(state) +{ + if (tap_move_map[state] != -1) + end_state = state; + else + { + ERROR("BUG: %i is not a valid end state", state); + exit(-1); + } +} + +void gw16012_state_move(void) +{ + int i=0, tms=0; + u8 tms_scan = TAP_MOVE(cur_state, end_state); + + gw16012_control(0x0); /* single-bit mode */ + + for (i = 0; i < 7; i++) + { + tms = (tms_scan >> i) & 1; + gw16012_data(tms << 1); /* output next TMS bit */ + } + + cur_state = end_state; +} + +void gw16012_runtest(int num_cycles) +{ + enum tap_state saved_end_state = end_state; + int i; + + /* only do a state_move when we're not already in RTI */ + if (cur_state != TAP_RTI) + { + gw16012_end_state(TAP_RTI); + gw16012_state_move(); + } + + for (i = 0; i < num_cycles; i++) + { + gw16012_control(0x0); /* single-bit mode */ + gw16012_data(0x0); /* TMS cycle with TMS low */ + } + + gw16012_end_state(saved_end_state); + if (cur_state != end_state) + gw16012_state_move(); +} + +void gw16012_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size) +{ + int bits_left = scan_size; + int bit_count = 0; + enum tap_state saved_end_state = end_state; + u8 scan_out, scan_in; + + if (ir_scan) + gw16012_end_state(TAP_SI); + else + gw16012_end_state(TAP_SD); + + gw16012_state_move(); + gw16012_end_state(saved_end_state); + + while (type == SCAN_OUT && ((bits_left - 1) > 7)) + { + gw16012_control(0x2); /* seven-bit mode */ + scan_out = buf_get_u32(buffer, bit_count, 7); + gw16012_data(scan_out); + bit_count += 7; + bits_left -= 7; + } + + gw16012_control(0x0); /* single-bit mode */ + while (bits_left-- > 0) + { + u8 tms = 0; + if (bits_left == 0) /* last bit */ + { + if ((ir_scan && (end_state == TAP_SI)) + || (!ir_scan && (end_state == TAP_SD))) + { + tms = 0; + } + else + { + tms = 2; + } + } + + scan_out = buf_get_u32(buffer, bit_count, 1); + gw16012_data(scan_out | tms); + if (type != SCAN_OUT) + { + gw16012_input(&scan_in); + buf_set_u32(buffer, bit_count, 1, ((scan_in & 0x08) >> 3)); + } + bit_count++; + } + + if (!((ir_scan && (end_state == TAP_SI)) || + (!ir_scan && (end_state == TAP_SD)))) + { + gw16012_data(0x0); + if (ir_scan) + cur_state = TAP_PI; + else + cur_state = TAP_PD; + + if (cur_state != end_state) + gw16012_state_move(); + } +} + +int gw16012_execute_queue(void) +{ + jtag_command_t *cmd = jtag_command_queue; /* currently processed command */ + int scan_size; + enum scan_type type; + u8 *buffer; + + while (cmd) + { + switch (cmd->type) + { + case JTAG_END_STATE: +#ifdef _DEBUG_JTAG_IO_ + DEBUG("end_state: %i", cmd->cmd.end_state->end_state); +#endif + if (cmd->cmd.end_state->end_state != -1) + gw16012_end_state(cmd->cmd.end_state->end_state); + break; + case JTAG_RESET: +#ifdef _DEBUG_JTAG_IO_ + DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); +#endif + if (cmd->cmd.reset->trst == 1) + { + cur_state = TAP_TLR; + } + gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); + break; + case JTAG_RUNTEST: +#ifdef _DEBUG_JTAG_IO_ + DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); +#endif + if (cmd->cmd.runtest->end_state != -1) + gw16012_end_state(cmd->cmd.runtest->end_state); + gw16012_runtest(cmd->cmd.runtest->num_cycles); + break; + case JTAG_STATEMOVE: +#ifdef _DEBUG_JTAG_IO_ + DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); +#endif + if (cmd->cmd.statemove->end_state != -1) + gw16012_end_state(cmd->cmd.statemove->end_state); + gw16012_state_move(); + break; + case JTAG_SCAN: + if (cmd->cmd.scan->end_state != -1) + gw16012_end_state(cmd->cmd.scan->end_state); + scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); + type = jtag_scan_type(cmd->cmd.scan); +#ifdef _DEBUG_JTAG_IO_ + DEBUG("%s scan (%i) %i bit end in %i", (cmd->cmd.scan->ir_scan) ? "ir" : "dr", + type, scan_size, cmd->cmd.scan->end_state); +#endif + gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); + if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) + return ERROR_JTAG_QUEUE_FAILED; + if (buffer) + free(buffer); + break; + case JTAG_SLEEP: +#ifdef _DEBUG_JTAG_IO_ + DEBUG("sleep", cmd->cmd.sleep->us); +#endif + jtag_sleep(cmd->cmd.sleep->us); + break; + default: + ERROR("BUG: unknown JTAG command type encountered"); + exit(-1); + } + cmd = cmd->next; + } + + return ERROR_OK; +} + +#if PARPORT_USE_GIVEIO == 1 +int gw16012_get_giveio_access() +{ + HANDLE h; + OSVERSIONINFO version; + + version.dwOSVersionInfoSize = sizeof version; + if (!GetVersionEx( &version )) { + errno = EINVAL; + return -1; + } + if (version.dwPlatformId != VER_PLATFORM_WIN32_NT) + return 0; + + h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + if (h == INVALID_HANDLE_VALUE) { + errno = ENODEV; + return -1; + } + + CloseHandle( h ); + + return 0; +} +#endif + +int gw16012_init(void) +{ +#if PARPORT_USE_PPDEV == 1 + char buffer[256]; + int i = 0; + u8 control_port; +#endif + u8 status_port; + +#if PARPORT_USE_PPDEV == 1 + if (device_handle>0) + { + ERROR("device is already opened"); + return ERROR_JTAG_INIT_FAILED; + } + +#ifdef __FreeBSD__ + DEBUG("opening /dev/ppi%d...", gw16012_port); + + snprintf(buffer, 256, "/dev/ppi%d", gw16012_port); + device_handle = open(buffer, O_WRONLY); +#else + DEBUG("opening /dev/parport%d...", gw16012_port); + + snprintf(buffer, 256, "/dev/parport%d", gw16012_port); + device_handle = open(buffer, O_WRONLY); +#endif + if (device_handle<0) + { + ERROR("cannot open device. check it exists and that user read and write rights are set"); + return ERROR_JTAG_INIT_FAILED; + } + + DEBUG("...open"); + +#ifndef __FreeBSD__ + i=ioctl(device_handle, PPCLAIM); + if (i<0) + { + ERROR("cannot claim device"); + return ERROR_JTAG_INIT_FAILED; + } + + i = PARPORT_MODE_COMPAT; + i= ioctl(device_handle, PPSETMODE, & i); + if (i<0) + { + ERROR(" cannot set compatible mode to device"); + return ERROR_JTAG_INIT_FAILED; + } + + i = IEEE1284_MODE_COMPAT; + i = ioctl(device_handle, PPNEGOT, & i); + if (i<0) + { + ERROR("cannot set compatible 1284 mode to device"); + return ERROR_JTAG_INIT_FAILED; + } +#endif +#else + if (gw16012_port == 0) + { + gw16012_port = 0x378; + WARNING("No gw16012 port specified, using default '0x378' (LPT1)"); + } + + DEBUG("requesting privileges for parallel port 0x%x...", gw16012_port); +#if PARPORT_USE_GIVEIO == 1 + if (gw16012_get_giveio_access() != 0) +#else /* PARPORT_USE_GIVEIO */ + if (ioperm(gw16012_port, 3, 1) != 0) +#endif /* PARPORT_USE_GIVEIO */ + { + ERROR("missing privileges for direct i/o"); + return ERROR_JTAG_INIT_FAILED; + } + DEBUG("...privileges granted"); +#endif /* PARPORT_USE_PPDEV */ + + gw16012_input(&status_port); + gw16012_msb = (status_port & 0x80) ^ 0x80; + + gw16012_speed(jtag_speed); + gw16012_reset(0, 0); + + return ERROR_OK; +} + +int gw16012_quit(void) +{ + + return ERROR_OK; +} + +int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc == 0) + return ERROR_OK; + + /* only if the port wasn't overwritten by cmdline */ + if (gw16012_port == 0) + gw16012_port = strtoul(args[0], NULL, 0); + + return ERROR_OK; +} diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index 4ba227c0..259a327d 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -144,6 +144,10 @@ jtag_event_callback_t *jtag_event_callbacks; extern jtag_interface_t at91rm9200_interface; #endif +#if BUILD_GW16012 == 1 + extern jtag_interface_t gw16012_interface; +#endif + jtag_interface_t *jtag_interfaces[] = { #if BUILD_PARPORT == 1 &parport_interface, @@ -162,6 +166,9 @@ jtag_interface_t *jtag_interfaces[] = { #endif #if BUILD_AT91RM9200 == 1 &at91rm9200_interface, +#endif +#if BUILD_GW16012 == 1 + &gw16012_interface, #endif NULL, }; @@ -959,7 +966,7 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer) if (cmd->fields[i].out_value) { #ifdef _DEBUG_JTAG_IO_ - char* char_buf = buf_to_str(cmd->fields[i].out_value, cmd->fields[i].num_bits, 16); + char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > 64) ? 64 : cmd->fields[i].num_bits, 16); #endif buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits); #ifdef _DEBUG_JTAG_IO_ @@ -993,7 +1000,7 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd) #ifdef _DEBUG_JTAG_IO_ char *char_buf; - char_buf = buf_to_str(captured, num_bits, 16); + char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16); DEBUG("fields[%i].in_value: 0x%s", i, char_buf); free(char_buf); #endif @@ -1031,9 +1038,9 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd) if ((cmd->fields[i].in_check_mask && buf_cmp_mask(captured, cmd->fields[i].in_check_value, cmd->fields[i].in_check_mask, num_bits)) || (!cmd->fields[i].in_check_mask && buf_cmp(captured, cmd->fields[i].in_check_mask, num_bits))) { - char *captured_char = buf_to_str(captured, num_bits, 16); - char *in_check_value_char = buf_to_str(cmd->fields[i].in_check_value, num_bits, 16); - char *in_check_mask_char = buf_to_str(cmd->fields[i].in_check_mask, num_bits, 16); + char *captured_char = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16); + char *in_check_value_char = buf_to_str(cmd->fields[i].in_check_value, (num_bits > 64) ? 64 : num_bits, 16); + char *in_check_mask_char = buf_to_str(cmd->fields[i].in_check_mask, (num_bits > 64) ? 64 : num_bits, 16); /* TODO: error reporting */ WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s check_mask: 0x%s", captured_char, in_check_value_char, in_check_mask_char); retval = ERROR_JTAG_QUEUE_FAILED; -- cgit v1.2.3