From: oharboe Date: Sun, 24 Feb 2008 17:10:48 +0000 (+0000) Subject: cosmetic fixes to debug output + phasing out printf() in favour of logging system... X-Git-Tag: v0.1.0~963 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=958f845f4b64448d72688c31f0c299de569961e6;p=openocd cosmetic fixes to debug output + phasing out printf() in favour of logging system. From Pavel Chromy git-svn-id: svn://svn.berlios.de/openocd/trunk@326 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- diff --git a/src/flash/s3c2440_nand.c b/src/flash/s3c2440_nand.c index fd197195..1390a3fb 100644 --- a/src/flash/s3c2440_nand.c +++ b/src/flash/s3c2440_nand.c @@ -1,179 +1,179 @@ -/* src/flash/s3c2440_nand.c - * - * S3C2440 OpenOCD NAND Flash controller support. - * - * Copyright 2007,2008 Ben Dooks - * - * 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. - * - * Many thanks to Simtec Electronics for sponsoring this work. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "replacements.h" -#include "log.h" - -#include -#include - -#include "nand.h" -#include "s3c24xx_nand.h" -#include "target.h" - -int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device); -int s3c2440_init(struct nand_device_s *device); -int s3c2440_nand_ready(struct nand_device_s *device, int timeout); - -nand_flash_controller_t s3c2440_nand_controller = -{ - .name = "s3c2440", - .nand_device_command = s3c2440_nand_device_command, - .register_commands = s3c24xx_register_commands, - .init = s3c2440_init, - .reset = s3c24xx_reset, - .command = s3c24xx_command, - .address = s3c24xx_address, - .write_data = s3c24xx_write_data, - .read_data = s3c24xx_read_data, - .write_page = s3c24xx_write_page, - .read_page = s3c24xx_read_page, - .write_block_data = s3c2440_write_block_data, - .read_block_data = s3c2440_read_block_data, - .controller_ready = s3c24xx_controller_ready, - .nand_ready = s3c2440_nand_ready, -}; - -int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, - char **args, int argc, - struct nand_device_s *device) -{ - s3c24xx_nand_controller_t *info; - - info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device); - if (info == NULL) { - return ERROR_NAND_DEVICE_INVALID; - } - - /* fill in the address fields for the core device */ - info->cmd = S3C2440_NFCMD; - info->addr = S3C2440_NFADDR; - info->data = S3C2440_NFDATA; - info->nfstat = S3C2440_NFSTAT; - - return ERROR_OK; -} - -int s3c2440_init(struct nand_device_s *device) -{ - s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv; - target_t *target = s3c24xx_info->target; - u32 version; - - target_write_u32(target, S3C2410_NFCONF, - S3C2440_NFCONF_TACLS(3) | - S3C2440_NFCONF_TWRPH0(7) | - S3C2440_NFCONF_TWRPH1(7)); - - target_write_u32(target, S3C2440_NFCONT, - S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE); - - return ERROR_OK; -} - -int s3c2440_nand_ready(struct nand_device_s *device, int timeout) -{ - s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv; - target_t *target = s3c24xx_info->target; - u8 status; - - if (target->state != TARGET_HALTED) { - ERROR("target must be halted to use S3C24XX NAND flash controller"); - return ERROR_NAND_OPERATION_FAILED; - } - - do { - target_read_u8(target, s3c24xx_info->nfstat, &status); - - if (status & S3C2440_NFSTAT_READY) - return 1; - - usleep(1000); - } while (timeout-- > 0); - - - return 0; -} - -/* use the fact we can read/write 4 bytes in one go via a single 32bit op */ - -int s3c2440_read_block_data(struct nand_device_s *device, u8 *data, int data_size) -{ - s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv; - target_t *target = s3c24xx_info->target; - u32 nfdata = s3c24xx_info->data; - u32 tmp; - - printf("%s: reading data: %p, %p, %d\n", __func__, device, data, data_size); - - if (target->state != TARGET_HALTED) { - ERROR("target must be halted to use S3C24XX NAND flash controller"); - return ERROR_NAND_OPERATION_FAILED; - } - - while (data_size >= 4) { - target_read_u32(target, nfdata, &tmp); - - data[0] = tmp; - data[1] = tmp >> 8; - data[2] = tmp >> 16; - data[3] = tmp >> 24; - - data_size -= 4; - data += 4; - } - - while (data_size > 0) { - target_read_u8(target, nfdata, data); - - data_size -= 1; - data += 1; - } - - return ERROR_OK; -} - -int s3c2440_write_block_data(struct nand_device_s *device, u8 *data, int data_size) -{ - s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv; - target_t *target = s3c24xx_info->target; - u32 nfdata = s3c24xx_info->data; - u32 tmp; - - if (target->state != TARGET_HALTED) { - ERROR("target must be halted to use S3C24XX NAND flash controller"); - return ERROR_NAND_OPERATION_FAILED; - } - - while (data_size >= 4) { - tmp = le_to_h_u32(data); - target_write_u32(target, nfdata, tmp); - - data_size -= 4; - data += 4; - } - - while (data_size > 0) { - target_write_u8(target, nfdata, *data); - - data_size -= 1; - data += 1; - } - - return ERROR_OK; -} +/* src/flash/s3c2440_nand.c + * + * S3C2440 OpenOCD NAND Flash controller support. + * + * Copyright 2007,2008 Ben Dooks + * + * 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. + * + * Many thanks to Simtec Electronics for sponsoring this work. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "replacements.h" +#include "log.h" + +#include +#include + +#include "nand.h" +#include "s3c24xx_nand.h" +#include "target.h" + +int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device); +int s3c2440_init(struct nand_device_s *device); +int s3c2440_nand_ready(struct nand_device_s *device, int timeout); + +nand_flash_controller_t s3c2440_nand_controller = +{ + .name = "s3c2440", + .nand_device_command = s3c2440_nand_device_command, + .register_commands = s3c24xx_register_commands, + .init = s3c2440_init, + .reset = s3c24xx_reset, + .command = s3c24xx_command, + .address = s3c24xx_address, + .write_data = s3c24xx_write_data, + .read_data = s3c24xx_read_data, + .write_page = s3c24xx_write_page, + .read_page = s3c24xx_read_page, + .write_block_data = s3c2440_write_block_data, + .read_block_data = s3c2440_read_block_data, + .controller_ready = s3c24xx_controller_ready, + .nand_ready = s3c2440_nand_ready, +}; + +int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, + char **args, int argc, + struct nand_device_s *device) +{ + s3c24xx_nand_controller_t *info; + + info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device); + if (info == NULL) { + return ERROR_NAND_DEVICE_INVALID; + } + + /* fill in the address fields for the core device */ + info->cmd = S3C2440_NFCMD; + info->addr = S3C2440_NFADDR; + info->data = S3C2440_NFDATA; + info->nfstat = S3C2440_NFSTAT; + + return ERROR_OK; +} + +int s3c2440_init(struct nand_device_s *device) +{ + s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv; + target_t *target = s3c24xx_info->target; + u32 version; + + target_write_u32(target, S3C2410_NFCONF, + S3C2440_NFCONF_TACLS(3) | + S3C2440_NFCONF_TWRPH0(7) | + S3C2440_NFCONF_TWRPH1(7)); + + target_write_u32(target, S3C2440_NFCONT, + S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE); + + return ERROR_OK; +} + +int s3c2440_nand_ready(struct nand_device_s *device, int timeout) +{ + s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv; + target_t *target = s3c24xx_info->target; + u8 status; + + if (target->state != TARGET_HALTED) { + ERROR("target must be halted to use S3C24XX NAND flash controller"); + return ERROR_NAND_OPERATION_FAILED; + } + + do { + target_read_u8(target, s3c24xx_info->nfstat, &status); + + if (status & S3C2440_NFSTAT_READY) + return 1; + + usleep(1000); + } while (timeout-- > 0); + + + return 0; +} + +/* use the fact we can read/write 4 bytes in one go via a single 32bit op */ + +int s3c2440_read_block_data(struct nand_device_s *device, u8 *data, int data_size) +{ + s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv; + target_t *target = s3c24xx_info->target; + u32 nfdata = s3c24xx_info->data; + u32 tmp; + + INFO("%s: reading data: %p, %p, %d\n", __func__, device, data, data_size); + + if (target->state != TARGET_HALTED) { + ERROR("target must be halted to use S3C24XX NAND flash controller"); + return ERROR_NAND_OPERATION_FAILED; + } + + while (data_size >= 4) { + target_read_u32(target, nfdata, &tmp); + + data[0] = tmp; + data[1] = tmp >> 8; + data[2] = tmp >> 16; + data[3] = tmp >> 24; + + data_size -= 4; + data += 4; + } + + while (data_size > 0) { + target_read_u8(target, nfdata, data); + + data_size -= 1; + data += 1; + } + + return ERROR_OK; +} + +int s3c2440_write_block_data(struct nand_device_s *device, u8 *data, int data_size) +{ + s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv; + target_t *target = s3c24xx_info->target; + u32 nfdata = s3c24xx_info->data; + u32 tmp; + + if (target->state != TARGET_HALTED) { + ERROR("target must be halted to use S3C24XX NAND flash controller"); + return ERROR_NAND_OPERATION_FAILED; + } + + while (data_size >= 4) { + tmp = le_to_h_u32(data); + target_write_u32(target, nfdata, tmp); + + data_size -= 4; + data += 4; + } + + while (data_size > 0) { + target_write_u8(target, nfdata, *data); + + data_size -= 1; + data += 1; + } + + return ERROR_OK; +} diff --git a/src/helper/log.c b/src/helper/log.c index b2f31dc2..7b7c9144 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -1,198 +1,198 @@ -/*************************************************************************** - * Copyright (C) 2005 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 "log.h" -#include "configuration.h" - -#include -#include -#include -#include -#include - -int debug_level = -1; - -static FILE* log_output; - -static void *privData; -static logCallback callback; - -void log_setCallback(logCallback c, void *p) -{ - callback = c; - privData = p; -} - -static char *log_strings[5] = -{ - "User: ", - "Error: ", - "Warning:", - "Info: ", - "Debug: " -}; - -void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...) -{ - static int count = 0; - count++; - va_list args; - char buffer[512]; - - if (level > debug_level) - return; - - va_start(args, format); - vsnprintf(buffer, 512, format, args); - - char *f = strrchr(file, '/'); - if (f != NULL) - file = f + 1; - - if (debug_level >= LOG_DEBUG) - { - /* print with count and time information */ - fprintf(log_output, "%s %d %ld %s:%d %s(): %s\n", log_strings[level+1], count, time(NULL), file, line, function, buffer); - } - else - { - /* do not print count and time */ - fprintf(log_output, "%s %s:%d %s(): %s\n", log_strings[level+1], file, line, function, buffer); - } - - fflush(log_output); - - va_end(args); - - /* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */ - if (callback && (level <= LOG_INFO)) - { - va_start(args, format); - callback(privData, file, line, function, format, args); - va_end(args); - } -} - -/* change the current debug level on the fly - * 0: only ERRORS - * 1: + WARNINGS - * 2: + INFORMATIONAL MSGS - * 3: + DEBUG MSGS - */ -int handle_debug_level_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - if (argc == 0) - command_print(cmd_ctx, "debug_level: %i", debug_level); - - if (argc > 0) - debug_level = strtoul(args[0], NULL, 0); - - if (debug_level < 0) - debug_level = 0; - - if (debug_level > 3) - debug_level = 3; - - return ERROR_OK; -} - -int handle_log_output_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - if (argc == 1) - { - FILE* file = fopen(args[0], "w"); - - if (file) - { - log_output = file; - } - } - - return ERROR_OK; -} - -int log_register_commands(struct command_context_s *cmd_ctx) -{ - register_command(cmd_ctx, NULL, "log_output", handle_log_output_command, - COMMAND_ANY, "redirect logging to (default: stderr)"); - register_command(cmd_ctx, NULL, "debug_level", handle_debug_level_command, - COMMAND_ANY, "adjust debug level <0-3>"); - - return ERROR_OK; -} - -int log_init(struct command_context_s *cmd_ctx) -{ - /* set defaults for daemon configuration, if not set by cmdline or cfgfile */ - if (debug_level == -1) - debug_level = LOG_INFO; - - if (log_output == NULL) - { - log_output = stderr; - } - - return ERROR_OK; -} - -int set_log_output(struct command_context_s *cmd_ctx, FILE *output) -{ - log_output = output; - return ERROR_OK; -} - -/* return allocated string w/printf() result */ -char *allocPrintf(const char *fmt, va_list ap) -{ - char *string = NULL; - - /* start by 0 to exercise all the code paths. Need minimum 2 bytes to - * fit 1 char and 0 terminator. */ - int size = 0; - int first = 1; - for (;;) - { - if ((string == NULL) || (!first)) - { - size = size * 2 + 2; - char *t = string; - string = realloc(string, size); - if (string == NULL) - { - if (t != NULL) - free(t); - return NULL; - } - } - - int ret; - ret = vsnprintf(string, size, fmt, ap); - /* NB! The result of the vsnprintf() might be an *EMPTY* string! */ - if ((ret >= 0) && ((ret + 1) < size)) - { - return string; - } - /* there was just enough or not enough space, allocate more. */ - first = 0; - } -} +/*************************************************************************** + * Copyright (C) 2005 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 "log.h" +#include "configuration.h" + +#include +#include +#include +#include +#include + +int debug_level = -1; + +static FILE* log_output; + +static void *privData; +static logCallback callback; + +void log_setCallback(logCallback c, void *p) +{ + callback = c; + privData = p; +} + +static char *log_strings[5] = +{ + "User: ", + "Error: ", + "Warning:", + "Info: ", + "Debug: " +}; + +void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...) +{ + static int count = 0; + count++; + va_list args; + char buffer[512]; + + if (level > debug_level) + return; + + va_start(args, format); + vsnprintf(buffer, 512, format, args); + + char *f = strrchr(file, '/'); + if (f != NULL) + file = f + 1; + + if (debug_level >= LOG_DEBUG) + { + /* print with count and time information */ + fprintf(log_output, "%s %d %ld %s:%d %s(): %s\n", log_strings[level+1], count, time(NULL), file, line, function, buffer); + } + else + { + /* do not print count and time */ + fprintf(log_output, "%s %s:%d %s(): %s\n", log_strings[level+1], file, line, function, buffer); + } + + fflush(log_output); + + va_end(args); + + /* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */ + if (callback && (level <= LOG_INFO)) + { + va_start(args, format); + callback(privData, file, line, function, format, args); + va_end(args); + } +} + +/* change the current debug level on the fly + * 0: only ERRORS + * 1: + WARNINGS + * 2: + INFORMATIONAL MSGS + * 3: + DEBUG MSGS + */ +int handle_debug_level_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc == 0) + command_print(cmd_ctx, "debug_level: %i", debug_level); + + if (argc > 0) + debug_level = strtoul(args[0], NULL, 0); + + if (debug_level < 0) + debug_level = 0; + + if (debug_level > 3) + debug_level = 3; + + return ERROR_OK; +} + +int handle_log_output_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc == 1) + { + FILE* file = fopen(args[0], "w"); + + if (file) + { + log_output = file; + } + } + + return ERROR_OK; +} + +int log_register_commands(struct command_context_s *cmd_ctx) +{ + register_command(cmd_ctx, NULL, "log_output", handle_log_output_command, + COMMAND_ANY, "redirect logging to (default: stderr)"); + register_command(cmd_ctx, NULL, "debug_level", handle_debug_level_command, + COMMAND_ANY, "adjust debug level <0-3>"); + + return ERROR_OK; +} + +int log_init(struct command_context_s *cmd_ctx) +{ + /* set defaults for daemon configuration, if not set by cmdline or cfgfile */ + if (debug_level == -1) + debug_level = LOG_INFO; + + if (log_output == NULL) + { + log_output = stderr; + } + + return ERROR_OK; +} + +int set_log_output(struct command_context_s *cmd_ctx, FILE *output) +{ + log_output = output; + return ERROR_OK; +} + +/* return allocated string w/printf() result */ +char *allocPrintf(const char *fmt, va_list ap) +{ + char *string = NULL; + + /* start by 0 to exercise all the code paths. Need minimum 2 bytes to + * fit 1 char and 0 terminator. */ + int size = 0; + int first = 1; + for (;;) + { + if ((string == NULL) || (!first)) + { + size = size * 2 + 2; + char *t = string; + string = realloc(string, size); + if (string == NULL) + { + if (t != NULL) + free(t); + return NULL; + } + } + + int ret; + ret = vsnprintf(string, size, fmt, ap); + /* NB! The result of the vsnprintf() might be an *EMPTY* string! */ + if ((ret >= 0) && ((ret + 1) < size)) + { + return string; + } + /* there was just enough or not enough space, allocate more. */ + first = 0; + } +} diff --git a/src/jtag/ep93xx.c b/src/jtag/ep93xx.c index f2e176fd..ebedfdfe 100644 --- a/src/jtag/ep93xx.c +++ b/src/jtag/ep93xx.c @@ -1,237 +1,237 @@ -/*************************************************************************** - * Copyright (C) 2005 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 "log.h" -#include "jtag.h" -#include "bitbang.h" - -#define TDO_BIT 1 -#define TDI_BIT 2 -#define TCK_BIT 4 -#define TMS_BIT 8 -#define TRST_BIT 16 -#define SRST_BIT 32 -#define VCC_BIT 64 - -/* system includes */ -#include -#include -#include -#include -#include -#include - -static u8 output_value = 0x0; -static int dev_mem_fd; -static void *gpio_controller; -static volatile u8 *gpio_data_register; -static volatile u8 *gpio_data_direction_register; - -/* low level command set - */ -int ep93xx_read(void); -void ep93xx_write(int tck, int tms, int tdi); -void ep93xx_reset(int trst, int srst); - -int ep93xx_speed(int speed); -int ep93xx_register_commands(struct command_context_s *cmd_ctx); -int ep93xx_init(void); -int ep93xx_quit(void); - -struct timespec ep93xx_zzzz; - -jtag_interface_t ep93xx_interface = -{ - .name = "ep93xx", - - .execute_queue = bitbang_execute_queue, - - .speed = ep93xx_speed, - .register_commands = ep93xx_register_commands, - .init = ep93xx_init, - .quit = ep93xx_quit, -}; - -bitbang_interface_t ep93xx_bitbang = -{ - .read = ep93xx_read, - .write = ep93xx_write, - .reset = ep93xx_reset, - .blink = 0; -}; - -int ep93xx_read(void) -{ - return !!(*gpio_data_register & TDO_BIT); -} - -void ep93xx_write(int tck, int tms, int tdi) -{ - if (tck) - output_value |= TCK_BIT; - else - output_value &= TCK_BIT; - - if (tms) - output_value |= TMS_BIT; - else - output_value &= TMS_BIT; - - if (tdi) - output_value |= TDI_BIT; - else - output_value &= TDI_BIT; - - *gpio_data_register = output_value; - nanosleep(ep93xx_zzzz); -} - -/* (1) assert or (0) deassert reset lines */ -void ep93xx_reset(int trst, int srst) -{ - if (trst == 0) - output_value |= TRST_BIT; - else if (trst == 1) - output_value &= TRST_BIT; - - if (srst == 0) - output_value |= SRST_BIT; - else if (srst == 1) - output_value &= SRST_BIT; - - *gpio_data_register = output_value; - nanosleep(ep93xx_zzzz); -} - -int ep93xx_speed(int speed) -{ - - return ERROR_OK; -} - -int ep93xx_register_commands(struct command_context_s *cmd_ctx) -{ - - return ERROR_OK; -} - -static int set_gonk_mode(void) -{ - void *syscon; - u32 devicecfg; - - syscon = mmap(NULL, 4096, PROT_READ | PROT_WRITE, - MAP_SHARED, dev_mem_fd, 0x80930000); - if (syscon == MAP_FAILED) { - perror("mmap"); - return ERROR_JTAG_INIT_FAILED; - } - - devicecfg = *((volatile int *)(syscon + 0x80)); - *((volatile int *)(syscon + 0xc0)) = 0xaa; - *((volatile int *)(syscon + 0x80)) = devicecfg | 0x08000000; - - munmap(syscon, 4096); - - return ERROR_OK; -} - -int ep93xx_init(void) -{ - int ret; - - bitbang_interface = &ep93xx_bitbang; - - ep93xx_zzzz.tv_sec = 0; - ep93xx_zzzz.tv_nsec = 10000000; - - dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); - if (dev_mem_fd < 0) { - perror("open"); - return ERROR_JTAG_INIT_FAILED; - } - - gpio_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE, - MAP_SHARED, dev_mem_fd, 0x80840000); - if (gpio_controller == MAP_FAILED) { - perror("mmap"); - close(dev_mem_fd); - return ERROR_JTAG_INIT_FAILED; - } - - ret = set_gonk_mode(); - if (ret != ERROR_OK) { - munmap(gpio_controller, 4096); - close(dev_mem_fd); - return ret; - } - -#if 0 - /* Use GPIO port A. */ - gpio_data_register = gpio_controller + 0x00; - gpio_data_direction_register = gpio_controller + 0x10; - - - /* Use GPIO port B. */ - gpio_data_register = gpio_controller + 0x04; - gpio_data_direction_register = gpio_controller + 0x14; - - /* Use GPIO port C. */ - gpio_data_register = gpio_controller + 0x08; - gpio_data_direction_register = gpio_controller + 0x18; - - /* Use GPIO port D. */ - gpio_data_register = gpio_controller + 0x0c; - gpio_data_direction_register = gpio_controller + 0x1c; -#endif - - /* Use GPIO port C. */ - gpio_data_register = gpio_controller + 0x08; - gpio_data_direction_register = gpio_controller + 0x18; - - printf("gpio_data_register = %p\n", gpio_data_register); - printf("gpio_data_direction_reg = %p\n", gpio_data_direction_register); - /* - * Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK - * TMS, TRST, SRST) as outputs. Drive TDI and TCK low, and - * TMS/TRST/SRST high. - */ - output_value = TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT; - *gpio_data_register = output_value; - nanosleep(ep93xx_zzzz); - - /* - * Configure the direction register. 1 = output, 0 = input. - */ - *gpio_data_direction_register = - TDI_BIT | TCK_BIT | TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT; - - nanosleep(ep93xx_zzzz); - return ERROR_OK; -} - -int ep93xx_quit(void) -{ - - return ERROR_OK; -} +/*************************************************************************** + * Copyright (C) 2005 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 "log.h" +#include "jtag.h" +#include "bitbang.h" + +#define TDO_BIT 1 +#define TDI_BIT 2 +#define TCK_BIT 4 +#define TMS_BIT 8 +#define TRST_BIT 16 +#define SRST_BIT 32 +#define VCC_BIT 64 + +/* system includes */ +#include +#include +#include +#include +#include +#include + +static u8 output_value = 0x0; +static int dev_mem_fd; +static void *gpio_controller; +static volatile u8 *gpio_data_register; +static volatile u8 *gpio_data_direction_register; + +/* low level command set + */ +int ep93xx_read(void); +void ep93xx_write(int tck, int tms, int tdi); +void ep93xx_reset(int trst, int srst); + +int ep93xx_speed(int speed); +int ep93xx_register_commands(struct command_context_s *cmd_ctx); +int ep93xx_init(void); +int ep93xx_quit(void); + +struct timespec ep93xx_zzzz; + +jtag_interface_t ep93xx_interface = +{ + .name = "ep93xx", + + .execute_queue = bitbang_execute_queue, + + .speed = ep93xx_speed, + .register_commands = ep93xx_register_commands, + .init = ep93xx_init, + .quit = ep93xx_quit, +}; + +bitbang_interface_t ep93xx_bitbang = +{ + .read = ep93xx_read, + .write = ep93xx_write, + .reset = ep93xx_reset, + .blink = 0; +}; + +int ep93xx_read(void) +{ + return !!(*gpio_data_register & TDO_BIT); +} + +void ep93xx_write(int tck, int tms, int tdi) +{ + if (tck) + output_value |= TCK_BIT; + else + output_value &= TCK_BIT; + + if (tms) + output_value |= TMS_BIT; + else + output_value &= TMS_BIT; + + if (tdi) + output_value |= TDI_BIT; + else + output_value &= TDI_BIT; + + *gpio_data_register = output_value; + nanosleep(ep93xx_zzzz); +} + +/* (1) assert or (0) deassert reset lines */ +void ep93xx_reset(int trst, int srst) +{ + if (trst == 0) + output_value |= TRST_BIT; + else if (trst == 1) + output_value &= TRST_BIT; + + if (srst == 0) + output_value |= SRST_BIT; + else if (srst == 1) + output_value &= SRST_BIT; + + *gpio_data_register = output_value; + nanosleep(ep93xx_zzzz); +} + +int ep93xx_speed(int speed) +{ + + return ERROR_OK; +} + +int ep93xx_register_commands(struct command_context_s *cmd_ctx) +{ + + return ERROR_OK; +} + +static int set_gonk_mode(void) +{ + void *syscon; + u32 devicecfg; + + syscon = mmap(NULL, 4096, PROT_READ | PROT_WRITE, + MAP_SHARED, dev_mem_fd, 0x80930000); + if (syscon == MAP_FAILED) { + perror("mmap"); + return ERROR_JTAG_INIT_FAILED; + } + + devicecfg = *((volatile int *)(syscon + 0x80)); + *((volatile int *)(syscon + 0xc0)) = 0xaa; + *((volatile int *)(syscon + 0x80)) = devicecfg | 0x08000000; + + munmap(syscon, 4096); + + return ERROR_OK; +} + +int ep93xx_init(void) +{ + int ret; + + bitbang_interface = &ep93xx_bitbang; + + ep93xx_zzzz.tv_sec = 0; + ep93xx_zzzz.tv_nsec = 10000000; + + dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); + if (dev_mem_fd < 0) { + perror("open"); + return ERROR_JTAG_INIT_FAILED; + } + + gpio_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE, + MAP_SHARED, dev_mem_fd, 0x80840000); + if (gpio_controller == MAP_FAILED) { + perror("mmap"); + close(dev_mem_fd); + return ERROR_JTAG_INIT_FAILED; + } + + ret = set_gonk_mode(); + if (ret != ERROR_OK) { + munmap(gpio_controller, 4096); + close(dev_mem_fd); + return ret; + } + +#if 0 + /* Use GPIO port A. */ + gpio_data_register = gpio_controller + 0x00; + gpio_data_direction_register = gpio_controller + 0x10; + + + /* Use GPIO port B. */ + gpio_data_register = gpio_controller + 0x04; + gpio_data_direction_register = gpio_controller + 0x14; + + /* Use GPIO port C. */ + gpio_data_register = gpio_controller + 0x08; + gpio_data_direction_register = gpio_controller + 0x18; + + /* Use GPIO port D. */ + gpio_data_register = gpio_controller + 0x0c; + gpio_data_direction_register = gpio_controller + 0x1c; +#endif + + /* Use GPIO port C. */ + gpio_data_register = gpio_controller + 0x08; + gpio_data_direction_register = gpio_controller + 0x18; + + INFO("gpio_data_register = %p\n", gpio_data_register); + INFO("gpio_data_direction_reg = %p\n", gpio_data_direction_register); + /* + * Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK + * TMS, TRST, SRST) as outputs. Drive TDI and TCK low, and + * TMS/TRST/SRST high. + */ + output_value = TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT; + *gpio_data_register = output_value; + nanosleep(ep93xx_zzzz); + + /* + * Configure the direction register. 1 = output, 0 = input. + */ + *gpio_data_direction_register = + TDI_BIT | TCK_BIT | TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT; + + nanosleep(ep93xx_zzzz); + return ERROR_OK; +} + +int ep93xx_quit(void) +{ + + return ERROR_OK; +} diff --git a/src/jtag/ft2232.c b/src/jtag/ft2232.c index 76741d9e..011eead1 100644 --- a/src/jtag/ft2232.c +++ b/src/jtag/ft2232.c @@ -1,2139 +1,2139 @@ -/*************************************************************************** - * Copyright (C) 2004, 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 - -#if IS_CYGWIN == 1 -#include "windows.h" -#undef ERROR -#endif - -#include "replacements.h" - -/* project specific includes */ -#include "log.h" -#include "types.h" -#include "jtag.h" -#include "configuration.h" -#include "time_support.h" - -/* system includes */ -#include -#include -#include - -/* FT2232 access library includes */ -#if BUILD_FT2232_FTD2XX == 1 -#include -#elif BUILD_FT2232_LIBFTDI == 1 -#include -#endif - -#include -#include - -/* enable this to debug io latency - */ -#if 0 -#define _DEBUG_USB_IO_ -#endif - -/* enable this to debug communication - */ -#if 0 -#define _DEBUG_USB_COMMS_ -#endif - -int ft2232_execute_queue(void); - -int ft2232_speed(int speed); -int ft2232_register_commands(struct command_context_s *cmd_ctx); -int ft2232_init(void); -int ft2232_quit(void); - -int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); - -char *ft2232_device_desc = NULL; -char *ft2232_serial = NULL; -char *ft2232_layout = NULL; -unsigned char ft2232_latency = 2; - -#define MAX_USB_IDS 8 -/* vid = pid = 0 marks the end of the list */ -static u16 ft2232_vid[MAX_USB_IDS+1] = { 0x0403, 0 }; -static u16 ft2232_pid[MAX_USB_IDS+1] = { 0x6010, 0 }; - -typedef struct ft2232_layout_s -{ - char* name; - int(*init)(void); - void(*reset)(int trst, int srst); - void(*blink)(void); -} ft2232_layout_t; - -/* init procedures for supported layouts */ -int usbjtag_init(void); -int jtagkey_init(void); -int olimex_jtag_init(void); -int flyswatter_init(void); -int turtle_init(void); -int comstick_init(void); -int stm32stick_init(void); - -/* reset procedures for supported layouts */ -void usbjtag_reset(int trst, int srst); -void jtagkey_reset(int trst, int srst); -void olimex_jtag_reset(int trst, int srst); -void flyswatter_reset(int trst, int srst); -void turtle_reset(int trst, int srst); -void comstick_reset(int trst, int srst); -void stm32stick_reset(int trst, int srst); - -/* blink procedures for layouts that support a blinking led */ -void olimex_jtag_blink(void); -void turtle_jtag_blink(void); - -ft2232_layout_t ft2232_layouts[] = -{ - {"usbjtag", usbjtag_init, usbjtag_reset, NULL}, - {"jtagkey", jtagkey_init, jtagkey_reset, NULL}, - {"jtagkey_prototype_v1", jtagkey_init, jtagkey_reset, NULL}, - {"oocdlink", jtagkey_init, jtagkey_reset, NULL}, - {"signalyzer", usbjtag_init, usbjtag_reset, NULL}, - {"evb_lm3s811", usbjtag_init, usbjtag_reset, NULL}, - {"olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink}, - {"flyswatter", flyswatter_init, flyswatter_reset, NULL}, - {"turtelizer2", turtle_init, turtle_reset, turtle_jtag_blink}, - {"comstick", comstick_init, comstick_reset, NULL}, - {"stm32stick", stm32stick_init, stm32stick_reset, NULL}, - {NULL, NULL, NULL}, -}; - -static u8 nTRST, nTRSTnOE, nSRST, nSRSTnOE; - -static ft2232_layout_t *layout; -static u8 low_output = 0x0; -static u8 low_direction = 0x0; -static u8 high_output = 0x0; -static u8 high_direction = 0x0; - -#if BUILD_FT2232_FTD2XX == 1 -static FT_HANDLE ftdih = NULL; -#elif BUILD_FT2232_LIBFTDI == 1 -static struct ftdi_context ftdic; -#endif - -static u8 *ft2232_buffer = NULL; -static int ft2232_buffer_size = 0; -static int ft2232_read_pointer = 0; -static int ft2232_expect_read = 0; -#define FT2232_BUFFER_SIZE 131072 -#define BUFFER_ADD ft2232_buffer[ft2232_buffer_size++] -#define BUFFER_READ ft2232_buffer[ft2232_read_pointer++] - -jtag_interface_t ft2232_interface = -{ - - .name = "ft2232", - - .execute_queue = ft2232_execute_queue, - - .speed = ft2232_speed, - .register_commands = ft2232_register_commands, - .init = ft2232_init, - .quit = ft2232_quit, -}; - -int ft2232_write(u8 *buf, int size, u32* bytes_written) -{ -#if BUILD_FT2232_FTD2XX == 1 - FT_STATUS status; - DWORD dw_bytes_written; - if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK) - { - *bytes_written = dw_bytes_written; - ERROR("FT_Write returned: %lu", status); - return ERROR_JTAG_DEVICE_ERROR; - } - else - { - *bytes_written = dw_bytes_written; - return ERROR_OK; - } -#elif BUILD_FT2232_LIBFTDI == 1 - int retval; - if ((retval = ftdi_write_data(&ftdic, buf, size)) < 0) - { - *bytes_written = 0; - ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - else - { - *bytes_written = retval; - return ERROR_OK; - } -#endif -} - -int ft2232_read(u8* buf, int size, u32* bytes_read) -{ -#if BUILD_FT2232_FTD2XX == 1 - DWORD dw_bytes_read; - FT_STATUS status; - int timeout = 5; - *bytes_read = 0; - - while ((*bytes_read < size) && timeout--) - { - if ((status = FT_Read(ftdih, buf + *bytes_read, size - - *bytes_read, &dw_bytes_read)) != FT_OK) - { - *bytes_read = 0; - ERROR("FT_Read returned: %lu", status); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read += dw_bytes_read; - } -#elif BUILD_FT2232_LIBFTDI == 1 - int retval; - int timeout = 100; - *bytes_read = 0; - - while ((*bytes_read < size) && timeout--) - { - if ((retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read)) < 0) - { - *bytes_read = 0; - ERROR("ftdi_read_data: %s", ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read += retval; - } -#endif - - if (*bytes_read < size) - { - ERROR("couldn't read the requested number of bytes from FT2232 device (%i < %i)", *bytes_read, size); - return ERROR_JTAG_DEVICE_ERROR; - } - - return ERROR_OK; -} - -int ft2232_speed(int speed) -{ - u8 buf[3]; - int retval; - u32 bytes_written; - - buf[0] = 0x86; /* command "set divisor" */ - buf[1] = speed & 0xff; /* valueL (0=6MHz, 1=3MHz, 2=2.0MHz, ...*/ - buf[2] = (speed >> 8) & 0xff; /* valueH */ - - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - if (((retval = ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't set FT2232 TCK speed"); - return retval; - } - - jtag_speed = speed; - - return ERROR_OK; -} - -int ft2232_register_commands(struct command_context_s *cmd_ctx) -{ - register_command(cmd_ctx, NULL, "ft2232_device_desc", ft2232_handle_device_desc_command, - COMMAND_CONFIG, NULL); - register_command(cmd_ctx, NULL, "ft2232_serial", ft2232_handle_serial_command, - COMMAND_CONFIG, NULL); - register_command(cmd_ctx, NULL, "ft2232_layout", ft2232_handle_layout_command, - COMMAND_CONFIG, NULL); - register_command(cmd_ctx, NULL, "ft2232_vid_pid", ft2232_handle_vid_pid_command, - COMMAND_CONFIG, NULL); - register_command(cmd_ctx, NULL, "ft2232_latency", ft2232_handle_latency_command, - COMMAND_CONFIG, NULL); - return ERROR_OK; -} - -void ft2232_end_state(enum tap_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 ft2232_read_scan(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; - - while(num_bytes-- > 1) - { - buffer[cur_byte] = BUFFER_READ; - cur_byte++; - bits_left -= 8; - } - - buffer[cur_byte] = 0x0; - - if (bits_left > 1) - { - buffer[cur_byte] = BUFFER_READ >> 1; - } - - buffer[cur_byte] = (buffer[cur_byte] | ((BUFFER_READ & 0x02) << 6)) >> (8 - bits_left); - -} - -void ft2232_debug_dump_buffer(void) -{ - int i; - char line[256]; - char *line_p = line; - - for (i = 0; i < ft2232_buffer_size; i++) - { - line_p += snprintf(line_p, 256 - (line_p - line), "%2.2x ", ft2232_buffer[i]); - if (i % 16 == 15) - { - DEBUG("%s", line); - line_p = line; - } - } - - if (line_p != line) - DEBUG("%s", line); -} - -int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last) -{ - jtag_command_t *cmd; - u8 *buffer; - int scan_size; - enum scan_type type; - int retval; - u32 bytes_written; - u32 bytes_read; - -#ifdef _DEBUG_USB_IO_ - struct timeval start, inter, inter2, end; - struct timeval d_inter, d_inter2, d_end; -#endif - -#ifdef _DEBUG_USB_COMMS_ - DEBUG("write buffer (size %i):", ft2232_buffer_size); - ft2232_debug_dump_buffer(); -#endif - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&start, NULL); -#endif - - if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK) - { - ERROR("couldn't write MPSSE commands to FT2232"); - exit(-1); - } - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&inter, NULL); -#endif - - if (ft2232_expect_read) - { - int timeout = 100; - ft2232_buffer_size = 0; - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&inter2, NULL); -#endif - - if ((retval = ft2232_read(ft2232_buffer, ft2232_expect_read, &bytes_read)) != ERROR_OK) - { - ERROR("couldn't read from FT2232"); - exit(-1); - } - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&end, NULL); - - timeval_subtract(&d_inter, &inter, &start); - timeval_subtract(&d_inter2, &inter2, &start); - timeval_subtract(&d_end, &end, &start); - - INFO("inter: %i.%i, inter2: %i.%i end: %i.%i", d_inter.tv_sec, d_inter.tv_usec, d_inter2.tv_sec, d_inter2.tv_usec, d_end.tv_sec, d_end.tv_usec); -#endif - - - ft2232_buffer_size = bytes_read; - - if (ft2232_expect_read != ft2232_buffer_size) - { - ERROR("ft2232_expect_read (%i) != ft2232_buffer_size (%i) (%i retries)", ft2232_expect_read, ft2232_buffer_size, 100 - timeout); - ft2232_debug_dump_buffer(); - - exit(-1); - } - -#ifdef _DEBUG_USB_COMMS_ - DEBUG("read buffer (%i retries): %i bytes", 100 - timeout, ft2232_buffer_size); - ft2232_debug_dump_buffer(); -#endif - } - - ft2232_expect_read = 0; - ft2232_read_pointer = 0; - - /* return ERROR_OK, unless a jtag_read_buffer returns a failed check - * that wasn't handled by a caller-provided error handler - */ - retval = ERROR_OK; - - cmd = first; - while (cmd != last) - { - switch (cmd->type) - { - case JTAG_SCAN: - type = jtag_scan_type(cmd->cmd.scan); - if (type != SCAN_OUT) - { - scan_size = jtag_scan_size(cmd->cmd.scan); - buffer = calloc(CEIL(scan_size, 8), 1); - ft2232_read_scan(type, buffer, scan_size); - if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - free(buffer); - } - break; - default: - break; - } - cmd = cmd->next; - } - - ft2232_buffer_size = 0; - - return retval; -} - -void ft2232_add_pathmove(pathmove_command_t *cmd) -{ - int num_states = cmd->num_states; - u8 tms_byte; - int state_count; - - state_count = 0; - while (num_states) - { - tms_byte = 0x0; - int bit_count = 0; - - /* command "Clock Data to TMS/CS Pin (no Read)" */ - BUFFER_ADD = 0x4b; - /* number of states remaining */ - BUFFER_ADD = (num_states % 7) - 1; - - while (num_states % 7) - { - if (tap_transitions[cur_state].low == cmd->path[state_count]) - buf_set_u32(&tms_byte, bit_count++, 1, 0x0); - else if (tap_transitions[cur_state].high == cmd->path[state_count]) - buf_set_u32(&tms_byte, bit_count++, 1, 0x1); - else - { - ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]); - exit(-1); - } - - cur_state = cmd->path[state_count]; - state_count++; - num_states--; - } - - BUFFER_ADD = tms_byte; - } - - end_state = cur_state; -} - -void ft2232_add_scan(int ir_scan, 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; - - 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; - /* scan 7 bit */ - BUFFER_ADD = 0x6; - /* TMS data bits */ - if (ir_scan) - { - BUFFER_ADD = TAP_MOVE(cur_state, TAP_SI); - cur_state = TAP_SI; - } - else - { - BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD); - cur_state = TAP_SD; - } - //DEBUG("added TMS scan (no read)"); - } - - /* 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); - 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) - { - 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]; - } - - 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; - } - 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) - { - 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; - else - last_bit = 0; - - /* process remaining bits but the last one */ - if (bits_left > 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]; - - if (type != SCAN_OUT) - thisrun_read += 2; - } - - if (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; - } - 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; - } - - 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; - - if (type == SCAN_IN) /* only from device to host */ - { - /* complete bytes */ - 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 += num_bytes + (CEIL(num_bytes, 65536)) * 3; - /* remaining bits -1 (up to 7) */ - predicted_size += ((scan_size - 1) % 8) ? 3 : 0; - } - - return predicted_size; -} - -int ft2232_predict_scan_in(int scan_size, enum scan_type type) -{ - int predicted_size = 0; - - if (type != SCAN_OUT) - { - /* complete bytes */ - predicted_size += (CEIL(scan_size, 8) > 1) ? (CEIL(scan_size, 8) - 1) : 0; - /* remaining bits - 1 */ - predicted_size += ((scan_size - 1) % 8) ? 1 : 0; - /* last bit (from TMS scan) */ - predicted_size += 1; - } - - //DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size); - - return predicted_size; -} - -void usbjtag_reset(int trst, int srst) -{ - if (trst == 1) - { - cur_state = TAP_TLR; - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - low_direction |= nTRSTnOE; /* switch to output pin (output is low) */ - else - low_output &= ~nTRST; /* switch output low */ - } - else if (trst == 0) - { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - low_direction &= ~nTRSTnOE; /* switch to input pin (high-Z + internal and external pullup) */ - else - low_output |= nTRST; /* switch output high */ - } - - if (srst == 1) - { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - low_output &= ~nSRST; /* switch output low */ - else - low_direction |= nSRSTnOE; /* switch to output pin (output is low) */ - } - else if (srst == 0) - { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - low_output |= nSRST; /* switch output high */ - else - low_direction &= ~nSRSTnOE; /* switch to input pin (high-Z) */ - } - - /* command "set data bits low byte" */ - BUFFER_ADD = 0x80; - BUFFER_ADD = low_output; - BUFFER_ADD = low_direction; - -} - -void jtagkey_reset(int trst, int srst) -{ - if (trst == 1) - { - cur_state = TAP_TLR; - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output &= ~nTRSTnOE; - else - high_output &= ~nTRST; - } - else if (trst == 0) - { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output |= nTRSTnOE; - else - high_output |= nTRST; - } - - if (srst == 1) - { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output &= ~nSRST; - else - high_output &= ~nSRSTnOE; - } - else if (srst == 0) - { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output |= nSRST; - else - high_output |= nSRSTnOE; - } - - /* command "set data bits high byte" */ - BUFFER_ADD = 0x82; - BUFFER_ADD = high_output; - BUFFER_ADD = high_direction; - DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); -} - -void olimex_jtag_reset(int trst, int srst) -{ - if (trst == 1) - { - cur_state = TAP_TLR; - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output &= ~nTRSTnOE; - else - high_output &= ~nTRST; - } - else if (trst == 0) - { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output |= nTRSTnOE; - else - high_output |= nTRST; - } - - if (srst == 1) - { - high_output |= nSRST; - } - else if (srst == 0) - { - high_output &= ~nSRST; - } - - /* command "set data bits high byte" */ - BUFFER_ADD = 0x82; - BUFFER_ADD = high_output; - BUFFER_ADD = high_direction; - DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); -} - -void flyswatter_reset(int trst, int srst) -{ - if (trst == 1) - { - cur_state = TAP_TLR; - low_output &= ~nTRST; - } - else if (trst == 0) - { - low_output |= nTRST; - } - - if (srst == 1) - { - low_output |= nSRST; - } - else if (srst == 0) - { - low_output &= ~nSRST; - } - - /* command "set data bits low byte" */ - BUFFER_ADD = 0x80; - BUFFER_ADD = low_output; - BUFFER_ADD = low_direction; - DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction); -} - -void turtle_reset(int trst, int srst) -{ - trst = trst; - - if (srst == 1) - { - low_output |= nSRST; - } - else if (srst == 0) - { - low_output &= ~nSRST; - } - - /* command "set data bits low byte" */ - BUFFER_ADD = 0x80; - BUFFER_ADD = low_output; - BUFFER_ADD = low_direction; - DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", srst, low_output, low_direction); -} - -void comstick_reset(int trst, int srst) -{ - if (trst == 1) - { - cur_state = TAP_TLR; - high_output &= ~nTRST; - } - else if (trst == 0) - { - high_output |= nTRST; - } - - if (srst == 1) - { - high_output &= ~nSRST; - } - else if (srst == 0) - { - high_output |= nSRST; - } - - /* command "set data bits high byte" */ - BUFFER_ADD = 0x82; - BUFFER_ADD = high_output; - BUFFER_ADD = high_direction; - DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); -} - -void stm32stick_reset(int trst, int srst) -{ - if (trst == 1) - { - cur_state = TAP_TLR; - high_output &= ~nTRST; - } - else if (trst == 0) - { - high_output |= nTRST; - } - - if (srst == 1) - { - low_output &= ~nSRST; - } - else if (srst == 0) - { - low_output |= nSRST; - } - - /* command "set data bits low byte" */ - BUFFER_ADD = 0x80; - BUFFER_ADD = low_output; - BUFFER_ADD = low_direction; - - /* command "set data bits high byte" */ - BUFFER_ADD = 0x82; - BUFFER_ADD = high_output; - BUFFER_ADD = high_direction; - DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); -} - -int ft2232_execute_queue() -{ - jtag_command_t *cmd = jtag_command_queue; /* currently processed command */ - jtag_command_t *first_unsent = cmd; /* next command that has to be sent */ - u8 *buffer; - int scan_size; /* size of IR or DR scan */ - enum scan_type type; - int i; - int predicted_size = 0; - int require_send = 0; - int retval; - - /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check - * that wasn't handled by a caller-provided error handler - */ - retval = ERROR_OK; - - ft2232_buffer_size = 0; - ft2232_expect_read = 0; - - /* blink, if the current layout has that feature */ - if (layout->blink) - layout->blink(); - - while (cmd) - { - switch(cmd->type) - { - case JTAG_END_STATE: - if (cmd->cmd.end_state->end_state != -1) - ft2232_end_state(cmd->cmd.end_state->end_state); - break; - case JTAG_RESET: - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3; - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) - { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - - layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); - require_send = 1; - -#ifdef _DEBUG_JTAG_IO_ - DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); -#endif - break; - case JTAG_RUNTEST: - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 0; - if (cur_state != TAP_RTI) - predicted_size += 3; - predicted_size += 3 * CEIL(cmd->cmd.runtest->num_cycles, 7); - if ((cmd->cmd.runtest->end_state != -1) && (cmd->cmd.runtest->end_state != TAP_RTI)) - predicted_size += 3; - if ((cmd->cmd.runtest->end_state == -1) && (end_state != TAP_RTI)) - predicted_size += 3; - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) - { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - if (cur_state != TAP_RTI) - { - /* 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_RTI); - cur_state = TAP_RTI; - require_send = 1; - } - i = cmd->cmd.runtest->num_cycles; - while (i > 0) - { - /* command "Clock Data to TMS/CS Pin (no Read)" */ - BUFFER_ADD = 0x4b; - /* scan 7 bit */ - BUFFER_ADD = (i > 7) ? 6 : (i - 1); - /* TMS data bits */ - BUFFER_ADD = 0x0; - cur_state = TAP_RTI; - i -= (i > 7) ? 7 : i; - //DEBUG("added TMS scan (no read)"); - } - if (cmd->cmd.runtest->end_state != -1) - ft2232_end_state(cmd->cmd.runtest->end_state); - if (cur_state != end_state) - { - /* 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, end_state); - cur_state = end_state; - //DEBUG("added TMS scan (no read)"); - } - require_send = 1; -#ifdef _DEBUG_JTAG_IO_ - DEBUG("runtest: %i, end in %i", cmd->cmd.runtest->num_cycles, end_state); -#endif - break; - case JTAG_STATEMOVE: - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3; - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) - { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - if (cmd->cmd.statemove->end_state != -1) - ft2232_end_state(cmd->cmd.statemove->end_state); - /* 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, end_state); - //DEBUG("added TMS scan (no read)"); - cur_state = end_state; - require_send = 1; -#ifdef _DEBUG_JTAG_IO_ - DEBUG("statemove: %i", end_state); -#endif - break; - case JTAG_PATHMOVE: - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7); - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) - { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - ft2232_add_pathmove(cmd->cmd.pathmove); - require_send = 1; -#ifdef _DEBUG_JTAG_IO_ - DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); -#endif - break; - case JTAG_SCAN: - 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 ((predicted_size + 1) > FT2232_BUFFER_SIZE) - { - DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)"); - /* unsent commands before this */ - if (first_unsent != cmd) - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - /* 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("ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)", first_unsent, cmd); - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - ft2232_expect_read += ft2232_predict_scan_in(scan_size, type); - //DEBUG("new read size: %i", ft2232_expect_read); - if (cmd->cmd.scan->end_state != -1) - ft2232_end_state(cmd->cmd.scan->end_state); - ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); - require_send = 1; - if (buffer) - free(buffer); -#ifdef _DEBUG_JTAG_IO_ - DEBUG("%s scan, %i bit, end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, end_state); -#endif - break; - case JTAG_SLEEP: - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - first_unsent = cmd->next; - jtag_sleep(cmd->cmd.sleep->us); -#ifdef _DEBUG_JTAG_IO_ - DEBUG("sleep %i usec", cmd->cmd.sleep->us); -#endif - break; - default: - ERROR("BUG: unknown JTAG command type encountered"); - exit(-1); - } - cmd = cmd->next; - } - - if (require_send > 0) - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - return retval; -} - -#if BUILD_FT2232_FTD2XX == 1 -static int ft2232_init_ftd2xx(u16 vid, u16 pid, int more, int *try_more) -{ - FT_STATUS status; - DWORD openex_flags = 0; - char *openex_string = NULL; - u8 latency_timer; - - DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", - ft2232_layout, vid, pid); - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - if ((status = FT_SetVIDPID(vid, pid)) != FT_OK) - { - WARNING("couldn't add %4.4x:%4.4x", - vid, pid); - } -#endif - - if (ft2232_device_desc && ft2232_serial) - { - WARNING("can't open by device description and serial number, giving precedence to serial"); - ft2232_device_desc = NULL; - } - - if (ft2232_device_desc) - { - openex_string = ft2232_device_desc; - openex_flags = FT_OPEN_BY_DESCRIPTION; - } - else if (ft2232_serial) - { - openex_string = ft2232_serial; - openex_flags = FT_OPEN_BY_SERIAL_NUMBER; - } - else - { - ERROR("neither device description nor serial number specified"); - ERROR("please add \"ft2232_device_desc \" or \"ft2232_serial \" to your .cfg file"); - - return ERROR_JTAG_INIT_FAILED; - } - - if ((status = FT_OpenEx(openex_string, openex_flags, &ftdih)) != FT_OK) - { - DWORD num_devices; - - if (more) { - WARNING("unable to open ftdi device (trying more): %lu", - status); - *try_more = 1; - return ERROR_JTAG_INIT_FAILED; - } - ERROR("unable to open ftdi device: %lu", status); - status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); - if (status == FT_OK) - { - char **desc_array = malloc(sizeof(char*) * (num_devices + 1)); - int i; - - for (i = 0; i < num_devices; i++) - desc_array[i] = malloc(64); - desc_array[num_devices] = NULL; - - status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags); - - if (status == FT_OK) - { - ERROR("ListDevices: %lu\n", num_devices); - for (i = 0; i < num_devices; i++) - ERROR("%i: %s", i, desc_array[i]); - } - - for (i = 0; i < num_devices; i++) - free(desc_array[i]); - free(desc_array); - } - else - { - printf("ListDevices: NONE\n"); - } - return ERROR_JTAG_INIT_FAILED; - } - - if ((status = FT_SetLatencyTimer(ftdih, ft2232_latency)) != FT_OK) - { - ERROR("unable to set latency timer: %lu", status); - return ERROR_JTAG_INIT_FAILED; - } - - if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK) - { - ERROR("unable to get latency timer: %lu", status); - return ERROR_JTAG_INIT_FAILED; - } - else - { - DEBUG("current latency timer: %i", latency_timer); - } - - if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK) - { - ERROR("unable to set timeouts: %lu", status); - return ERROR_JTAG_INIT_FAILED; - } - - if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK) - { - ERROR("unable to enable bit i/o mode: %lu", status); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int ft2232_purge_ftd2xx(void) -{ - FT_STATUS status; - - if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK) - { - ERROR("error purging ftd2xx device: %lu", status); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} -#endif /* BUILD_FT2232_FTD2XX == 1 */ - -#if BUILD_FT2232_LIBFTDI == 1 -static int ft2232_init_libftdi(u16 vid, u16 pid, int more, int *try_more) -{ - u8 latency_timer; - - DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)", - ft2232_layout, vid, pid); - - if (ftdi_init(&ftdic) < 0) - return ERROR_JTAG_INIT_FAILED; - - /* context, vendor id, product id */ - if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc, - ft2232_serial) < 0) { - if (more) - WARNING("unable to open ftdi device (trying more): %s", - ftdic.error_str); - else - ERROR("unable to open ftdi device: %s", ftdic.error_str); - *try_more = 1; - return ERROR_JTAG_INIT_FAILED; - } - - if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0) - { - ERROR("unable to select FT2232 channel A: %s", ftdic.error_str); - return ERROR_JTAG_INIT_FAILED; - } - - if (ftdi_usb_reset(&ftdic) < 0) - { - ERROR("unable to reset ftdi device"); - return ERROR_JTAG_INIT_FAILED; - } - - if (ftdi_set_latency_timer(&ftdic, ft2232_latency) < 0) - { - ERROR("unable to set latency timer"); - return ERROR_JTAG_INIT_FAILED; - } - - if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) - { - ERROR("unable to get latency timer"); - return ERROR_JTAG_INIT_FAILED; - } - else - { - DEBUG("current latency timer: %i", latency_timer); - } - - ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */ - - return ERROR_OK; -} - -static int ft2232_purge_libftdi(void) -{ - if (ftdi_usb_purge_buffers(&ftdic) < 0) - { - ERROR("ftdi_purge_buffers: %s", ftdic.error_str); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} -#endif /* BUILD_FT2232_LIBFTDI == 1 */ - -int ft2232_init(void) -{ - u8 buf[1]; - int retval; - u32 bytes_written; - ft2232_layout_t *cur_layout = ft2232_layouts; - int i; - - if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0)) - { - ft2232_layout = "usbjtag"; - WARNING("No ft2232 layout specified, using default 'usbjtag'"); - } - - while (cur_layout->name) - { - if (strcmp(cur_layout->name, ft2232_layout) == 0) - { - layout = cur_layout; - break; - } - cur_layout++; - } - - if (!layout) - { - ERROR("No matching layout found for %s", ft2232_layout); - return ERROR_JTAG_INIT_FAILED; - } - - for (i = 0; 1; i++) { - /* - * "more indicates that there are more IDs to try, so we should - * not print an error for an ID mismatch (but for anything - * else, we should). - * - * try_more indicates that the error code returned indicates an - * ID mismatch (and nothing else) and that we should proceeed - * with the next ID pair. - */ - int more = ft2232_vid[i+1] || ft2232_pid[i+1]; - int try_more = 0; - -#if BUILD_FT2232_FTD2XX == 1 - retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i], - more, &try_more); -#elif BUILD_FT2232_LIBFTDI == 1 - retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i], - more, &try_more); -#endif - if (retval >= 0) - break; - if (!more || !try_more) - return retval; - } - - ft2232_buffer_size = 0; - ft2232_buffer = malloc(FT2232_BUFFER_SIZE); - - if (layout->init() != ERROR_OK) - return ERROR_JTAG_INIT_FAILED; - - ft2232_speed(jtag_speed); - - buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */ - if (((retval = ft2232_write(buf, 1, &bytes_written)) != ERROR_OK) || (bytes_written != 1)) - { - ERROR("couldn't write to FT2232 to disable loopback"); - return ERROR_JTAG_INIT_FAILED; - } - -#if BUILD_FT2232_FTD2XX == 1 - return ft2232_purge_ftd2xx(); -#elif BUILD_FT2232_LIBFTDI == 1 - return ft2232_purge_libftdi(); -#endif - - return ERROR_OK; -} - -int usbjtag_init(void) -{ - u8 buf[3]; - u32 bytes_written; - - low_output = 0x08; - low_direction = 0x0b; - - if (strcmp(ft2232_layout, "usbjtag") == 0) - { - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x40; - nSRSTnOE = 0x40; - } - else if (strcmp(ft2232_layout, "signalyzer") == 0) - { - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x20; - nSRSTnOE = 0x20; - } - else if (strcmp(ft2232_layout, "evb_lm3s811") == 0) - { - nTRST = 0x0; - nTRSTnOE = 0x00; - nSRST = 0x20; - nSRSTnOE = 0x20; - low_output = 0x88; - low_direction = 0x8b; - } - else - { - ERROR("BUG: usbjtag_init called for unknown layout '%s'", ft2232_layout); - return ERROR_JTAG_INIT_FAILED; - } - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - { - low_direction &= ~nTRSTnOE; /* nTRST input */ - low_output &= ~nTRST; /* nTRST = 0 */ - } - else - { - low_direction |= nTRSTnOE; /* nTRST output */ - low_output |= nTRST; /* nTRST = 1 */ - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - { - low_direction |= nSRSTnOE; /* nSRST output */ - low_output |= nSRST; /* nSRST = 1 */ - } - else - { - low_direction &= ~nSRSTnOE; /* nSRST input */ - low_output &= ~nSRST; /* nSRST = 0 */ - } - - /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, xRST high) */ - buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in */ - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'USBJTAG' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -int jtagkey_init(void) -{ - u8 buf[3]; - u32 bytes_written; - - low_output = 0x08; - low_direction = 0x1b; - - /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ - buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - if (strcmp(layout->name, "jtagkey") == 0) - { - nTRST = 0x01; - nTRSTnOE = 0x4; - nSRST = 0x02; - nSRSTnOE = 0x08; - } - else if ((strcmp(layout->name, "jtagkey_prototype_v1") == 0) || - (strcmp(layout->name, "oocdlink") == 0)) - { - nTRST = 0x02; - nTRSTnOE = 0x1; - nSRST = 0x08; - nSRSTnOE = 0x04; - } - else - { - ERROR("BUG: jtagkey_init called for non jtagkey layout"); - exit(-1); - } - - high_output = 0x0; - high_direction = 0x0f; - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - { - high_output |= nTRSTnOE; - high_output &= ~nTRST; - } - else - { - high_output &= ~nTRSTnOE; - high_output |= nTRST; - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - { - high_output &= ~nSRSTnOE; - high_output |= nSRST; - } - else - { - high_output |= nSRSTnOE; - high_output &= ~nSRST; - } - - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; /* value */ - buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -int olimex_jtag_init(void) -{ - u8 buf[3]; - u32 bytes_written; - - low_output = 0x08; - low_direction = 0x1b; - - /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ - buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x4; - nSRST = 0x02; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x0; - high_direction = 0x0f; - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - { - high_output |= nTRSTnOE; - high_output &= ~nTRST; - } - else - { - high_output &= ~nTRSTnOE; - high_output |= nTRST; - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - { - ERROR("can't set nSRST to push-pull on the Olimex ARM-USB-OCD"); - } - else - { - high_output &= ~nSRST; - } - - /* turn red LED on */ - high_output |= 0x08; - - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; /* value */ - buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -int flyswatter_init(void) -{ - u8 buf[3]; - u32 bytes_written; - - low_output = 0x18; - low_direction = 0xfb; - - /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ - buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE[12]=out, n[ST]srst=out */ - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x10; - nTRSTnOE = 0x0; /* not output enable for nTRST */ - nSRST = 0x20; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x00; - high_direction = 0x0c; - - /* turn red LED1 on, LED2 off */ - high_output |= 0x08; - - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; /* value */ - buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -int turtle_init(void) -{ - u8 buf[3]; - u32 bytes_written; - - low_output = 0x08; - low_direction = 0x5b; - - /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ - buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nSRST = 0x40; - - high_output = 0x00; - high_direction = 0x0C; - - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; - buf[2] = high_direction; - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -int comstick_init(void) -{ - u8 buf[3]; - u32 bytes_written; - - low_output = 0x08; - low_direction = 0x0b; - - /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ - buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'comstick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x00; /* no output enable for nTRST */ - nSRST = 0x02; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x03; - high_direction = 0x03; - - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; - buf[2] = high_direction; - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'comstick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -int stm32stick_init(void) -{ - u8 buf[3]; - u32 bytes_written; - - low_output = 0x88; - low_direction = 0x8b; - - /* initialize low byte for jtag */ - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ - buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x00; /* no output enable for nTRST */ - nSRST = 0x80; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x01; - high_direction = 0x03; - - /* initialize high port */ - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = high_output; - buf[2] = high_direction; - DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) - { - ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -void olimex_jtag_blink(void) -{ - /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 - * ACBUS3 is bit 3 of the GPIOH port - */ - if (high_output & 0x08) - { - /* set port pin high */ - high_output &= 0x07; - } - else - { - /* set port pin low */ - high_output |= 0x08; - } - - BUFFER_ADD = 0x82; - BUFFER_ADD = high_output; - BUFFER_ADD = high_direction; -} - -void turtle_jtag_blink(void) -{ - /* - * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3 - */ - if (high_output & 0x08) - { - high_output = 0x04; - } - else - { - high_output = 0x08; - } - - BUFFER_ADD = 0x82; - BUFFER_ADD = high_output; - BUFFER_ADD = high_direction; -} - - -int ft2232_quit(void) -{ -#if BUILD_FT2232_FTD2XX == 1 - FT_STATUS status; - - status = FT_Close(ftdih); -#elif BUILD_FT2232_LIBFTDI == 1 - ftdi_disable_bitbang(&ftdic); - - ftdi_usb_close(&ftdic); - - ftdi_deinit(&ftdic); -#endif - - free(ft2232_buffer); - ft2232_buffer = NULL; - - return ERROR_OK; -} - -int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - if (argc == 1) - { - ft2232_device_desc = strdup(args[0]); - } - else - { - ERROR("expected exactly one argument to ft2232_device_desc "); - } - - return ERROR_OK; -} - -int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - if (argc == 1) - { - ft2232_serial = strdup(args[0]); - } - else - { - ERROR("expected exactly one argument to ft2232_serial "); - } - - return ERROR_OK; -} - -int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - if (argc == 0) - return ERROR_OK; - - ft2232_layout = malloc(strlen(args[0]) + 1); - strcpy(ft2232_layout, args[0]); - - return ERROR_OK; -} - -int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - int i; - - if (argc > MAX_USB_IDS*2) { - WARNING("ignoring extra IDs in ft2232_vid_pid " - "(maximum is %d pairs)", MAX_USB_IDS); - argc = MAX_USB_IDS*2; - } - if (argc < 2 || (argc & 1)) - { - WARNING("incomplete ft2232_vid_pid configuration directive"); - if (argc < 2) - return ERROR_OK; - } - - for (i = 0; i+1 < argc; i += 2) { - ft2232_vid[i >> 1] = strtol(args[i], NULL, 0); - ft2232_pid[i >> 1] = strtol(args[i+1], NULL, 0); - } - /* - * Explicitly terminate, in case there are multiples instances of - * ft2232_vid_pid. - */ - ft2232_vid[i >> 1] = ft2232_pid[i >> 1] = 0; - - return ERROR_OK; -} - -int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - if (argc == 1) - { - ft2232_latency = atoi(args[0]); - } - else - { - ERROR("expected exactly one argument to ft2232_latency "); - } - - return ERROR_OK; -} - - +/*************************************************************************** + * Copyright (C) 2004, 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 + +#if IS_CYGWIN == 1 +#include "windows.h" +#undef ERROR +#endif + +#include "replacements.h" + +/* project specific includes */ +#include "log.h" +#include "types.h" +#include "jtag.h" +#include "configuration.h" +#include "time_support.h" + +/* system includes */ +#include +#include +#include + +/* FT2232 access library includes */ +#if BUILD_FT2232_FTD2XX == 1 +#include +#elif BUILD_FT2232_LIBFTDI == 1 +#include +#endif + +#include +#include + +/* enable this to debug io latency + */ +#if 0 +#define _DEBUG_USB_IO_ +#endif + +/* enable this to debug communication + */ +#if 0 +#define _DEBUG_USB_COMMS_ +#endif + +int ft2232_execute_queue(void); + +int ft2232_speed(int speed); +int ft2232_register_commands(struct command_context_s *cmd_ctx); +int ft2232_init(void); +int ft2232_quit(void); + +int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); + +char *ft2232_device_desc = NULL; +char *ft2232_serial = NULL; +char *ft2232_layout = NULL; +unsigned char ft2232_latency = 2; + +#define MAX_USB_IDS 8 +/* vid = pid = 0 marks the end of the list */ +static u16 ft2232_vid[MAX_USB_IDS+1] = { 0x0403, 0 }; +static u16 ft2232_pid[MAX_USB_IDS+1] = { 0x6010, 0 }; + +typedef struct ft2232_layout_s +{ + char* name; + int(*init)(void); + void(*reset)(int trst, int srst); + void(*blink)(void); +} ft2232_layout_t; + +/* init procedures for supported layouts */ +int usbjtag_init(void); +int jtagkey_init(void); +int olimex_jtag_init(void); +int flyswatter_init(void); +int turtle_init(void); +int comstick_init(void); +int stm32stick_init(void); + +/* reset procedures for supported layouts */ +void usbjtag_reset(int trst, int srst); +void jtagkey_reset(int trst, int srst); +void olimex_jtag_reset(int trst, int srst); +void flyswatter_reset(int trst, int srst); +void turtle_reset(int trst, int srst); +void comstick_reset(int trst, int srst); +void stm32stick_reset(int trst, int srst); + +/* blink procedures for layouts that support a blinking led */ +void olimex_jtag_blink(void); +void turtle_jtag_blink(void); + +ft2232_layout_t ft2232_layouts[] = +{ + {"usbjtag", usbjtag_init, usbjtag_reset, NULL}, + {"jtagkey", jtagkey_init, jtagkey_reset, NULL}, + {"jtagkey_prototype_v1", jtagkey_init, jtagkey_reset, NULL}, + {"oocdlink", jtagkey_init, jtagkey_reset, NULL}, + {"signalyzer", usbjtag_init, usbjtag_reset, NULL}, + {"evb_lm3s811", usbjtag_init, usbjtag_reset, NULL}, + {"olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink}, + {"flyswatter", flyswatter_init, flyswatter_reset, NULL}, + {"turtelizer2", turtle_init, turtle_reset, turtle_jtag_blink}, + {"comstick", comstick_init, comstick_reset, NULL}, + {"stm32stick", stm32stick_init, stm32stick_reset, NULL}, + {NULL, NULL, NULL}, +}; + +static u8 nTRST, nTRSTnOE, nSRST, nSRSTnOE; + +static ft2232_layout_t *layout; +static u8 low_output = 0x0; +static u8 low_direction = 0x0; +static u8 high_output = 0x0; +static u8 high_direction = 0x0; + +#if BUILD_FT2232_FTD2XX == 1 +static FT_HANDLE ftdih = NULL; +#elif BUILD_FT2232_LIBFTDI == 1 +static struct ftdi_context ftdic; +#endif + +static u8 *ft2232_buffer = NULL; +static int ft2232_buffer_size = 0; +static int ft2232_read_pointer = 0; +static int ft2232_expect_read = 0; +#define FT2232_BUFFER_SIZE 131072 +#define BUFFER_ADD ft2232_buffer[ft2232_buffer_size++] +#define BUFFER_READ ft2232_buffer[ft2232_read_pointer++] + +jtag_interface_t ft2232_interface = +{ + + .name = "ft2232", + + .execute_queue = ft2232_execute_queue, + + .speed = ft2232_speed, + .register_commands = ft2232_register_commands, + .init = ft2232_init, + .quit = ft2232_quit, +}; + +int ft2232_write(u8 *buf, int size, u32* bytes_written) +{ +#if BUILD_FT2232_FTD2XX == 1 + FT_STATUS status; + DWORD dw_bytes_written; + if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK) + { + *bytes_written = dw_bytes_written; + ERROR("FT_Write returned: %lu", status); + return ERROR_JTAG_DEVICE_ERROR; + } + else + { + *bytes_written = dw_bytes_written; + return ERROR_OK; + } +#elif BUILD_FT2232_LIBFTDI == 1 + int retval; + if ((retval = ftdi_write_data(&ftdic, buf, size)) < 0) + { + *bytes_written = 0; + ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic)); + return ERROR_JTAG_DEVICE_ERROR; + } + else + { + *bytes_written = retval; + return ERROR_OK; + } +#endif +} + +int ft2232_read(u8* buf, int size, u32* bytes_read) +{ +#if BUILD_FT2232_FTD2XX == 1 + DWORD dw_bytes_read; + FT_STATUS status; + int timeout = 5; + *bytes_read = 0; + + while ((*bytes_read < size) && timeout--) + { + if ((status = FT_Read(ftdih, buf + *bytes_read, size - + *bytes_read, &dw_bytes_read)) != FT_OK) + { + *bytes_read = 0; + ERROR("FT_Read returned: %lu", status); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_read += dw_bytes_read; + } +#elif BUILD_FT2232_LIBFTDI == 1 + int retval; + int timeout = 100; + *bytes_read = 0; + + while ((*bytes_read < size) && timeout--) + { + if ((retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read)) < 0) + { + *bytes_read = 0; + ERROR("ftdi_read_data: %s", ftdi_get_error_string(&ftdic)); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_read += retval; + } +#endif + + if (*bytes_read < size) + { + ERROR("couldn't read the requested number of bytes from FT2232 device (%i < %i)", *bytes_read, size); + return ERROR_JTAG_DEVICE_ERROR; + } + + return ERROR_OK; +} + +int ft2232_speed(int speed) +{ + u8 buf[3]; + int retval; + u32 bytes_written; + + buf[0] = 0x86; /* command "set divisor" */ + buf[1] = speed & 0xff; /* valueL (0=6MHz, 1=3MHz, 2=2.0MHz, ...*/ + buf[2] = (speed >> 8) & 0xff; /* valueH */ + + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + if (((retval = ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't set FT2232 TCK speed"); + return retval; + } + + jtag_speed = speed; + + return ERROR_OK; +} + +int ft2232_register_commands(struct command_context_s *cmd_ctx) +{ + register_command(cmd_ctx, NULL, "ft2232_device_desc", ft2232_handle_device_desc_command, + COMMAND_CONFIG, NULL); + register_command(cmd_ctx, NULL, "ft2232_serial", ft2232_handle_serial_command, + COMMAND_CONFIG, NULL); + register_command(cmd_ctx, NULL, "ft2232_layout", ft2232_handle_layout_command, + COMMAND_CONFIG, NULL); + register_command(cmd_ctx, NULL, "ft2232_vid_pid", ft2232_handle_vid_pid_command, + COMMAND_CONFIG, NULL); + register_command(cmd_ctx, NULL, "ft2232_latency", ft2232_handle_latency_command, + COMMAND_CONFIG, NULL); + return ERROR_OK; +} + +void ft2232_end_state(enum tap_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 ft2232_read_scan(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; + + while(num_bytes-- > 1) + { + buffer[cur_byte] = BUFFER_READ; + cur_byte++; + bits_left -= 8; + } + + buffer[cur_byte] = 0x0; + + if (bits_left > 1) + { + buffer[cur_byte] = BUFFER_READ >> 1; + } + + buffer[cur_byte] = (buffer[cur_byte] | ((BUFFER_READ & 0x02) << 6)) >> (8 - bits_left); + +} + +void ft2232_debug_dump_buffer(void) +{ + int i; + char line[256]; + char *line_p = line; + + for (i = 0; i < ft2232_buffer_size; i++) + { + line_p += snprintf(line_p, 256 - (line_p - line), "%2.2x ", ft2232_buffer[i]); + if (i % 16 == 15) + { + DEBUG("%s", line); + line_p = line; + } + } + + if (line_p != line) + DEBUG("%s", line); +} + +int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last) +{ + jtag_command_t *cmd; + u8 *buffer; + int scan_size; + enum scan_type type; + int retval; + u32 bytes_written; + u32 bytes_read; + +#ifdef _DEBUG_USB_IO_ + struct timeval start, inter, inter2, end; + struct timeval d_inter, d_inter2, d_end; +#endif + +#ifdef _DEBUG_USB_COMMS_ + DEBUG("write buffer (size %i):", ft2232_buffer_size); + ft2232_debug_dump_buffer(); +#endif + +#ifdef _DEBUG_USB_IO_ + gettimeofday(&start, NULL); +#endif + + if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK) + { + ERROR("couldn't write MPSSE commands to FT2232"); + exit(-1); + } + +#ifdef _DEBUG_USB_IO_ + gettimeofday(&inter, NULL); +#endif + + if (ft2232_expect_read) + { + int timeout = 100; + ft2232_buffer_size = 0; + +#ifdef _DEBUG_USB_IO_ + gettimeofday(&inter2, NULL); +#endif + + if ((retval = ft2232_read(ft2232_buffer, ft2232_expect_read, &bytes_read)) != ERROR_OK) + { + ERROR("couldn't read from FT2232"); + exit(-1); + } + +#ifdef _DEBUG_USB_IO_ + gettimeofday(&end, NULL); + + timeval_subtract(&d_inter, &inter, &start); + timeval_subtract(&d_inter2, &inter2, &start); + timeval_subtract(&d_end, &end, &start); + + INFO("inter: %i.%i, inter2: %i.%i end: %i.%i", d_inter.tv_sec, d_inter.tv_usec, d_inter2.tv_sec, d_inter2.tv_usec, d_end.tv_sec, d_end.tv_usec); +#endif + + + ft2232_buffer_size = bytes_read; + + if (ft2232_expect_read != ft2232_buffer_size) + { + ERROR("ft2232_expect_read (%i) != ft2232_buffer_size (%i) (%i retries)", ft2232_expect_read, ft2232_buffer_size, 100 - timeout); + ft2232_debug_dump_buffer(); + + exit(-1); + } + +#ifdef _DEBUG_USB_COMMS_ + DEBUG("read buffer (%i retries): %i bytes", 100 - timeout, ft2232_buffer_size); + ft2232_debug_dump_buffer(); +#endif + } + + ft2232_expect_read = 0; + ft2232_read_pointer = 0; + + /* return ERROR_OK, unless a jtag_read_buffer returns a failed check + * that wasn't handled by a caller-provided error handler + */ + retval = ERROR_OK; + + cmd = first; + while (cmd != last) + { + switch (cmd->type) + { + case JTAG_SCAN: + type = jtag_scan_type(cmd->cmd.scan); + if (type != SCAN_OUT) + { + scan_size = jtag_scan_size(cmd->cmd.scan); + buffer = calloc(CEIL(scan_size, 8), 1); + ft2232_read_scan(type, buffer, scan_size); + if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + free(buffer); + } + break; + default: + break; + } + cmd = cmd->next; + } + + ft2232_buffer_size = 0; + + return retval; +} + +void ft2232_add_pathmove(pathmove_command_t *cmd) +{ + int num_states = cmd->num_states; + u8 tms_byte; + int state_count; + + state_count = 0; + while (num_states) + { + tms_byte = 0x0; + int bit_count = 0; + + /* command "Clock Data to TMS/CS Pin (no Read)" */ + BUFFER_ADD = 0x4b; + /* number of states remaining */ + BUFFER_ADD = (num_states % 7) - 1; + + while (num_states % 7) + { + if (tap_transitions[cur_state].low == cmd->path[state_count]) + buf_set_u32(&tms_byte, bit_count++, 1, 0x0); + else if (tap_transitions[cur_state].high == cmd->path[state_count]) + buf_set_u32(&tms_byte, bit_count++, 1, 0x1); + else + { + ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]); + exit(-1); + } + + cur_state = cmd->path[state_count]; + state_count++; + num_states--; + } + + BUFFER_ADD = tms_byte; + } + + end_state = cur_state; +} + +void ft2232_add_scan(int ir_scan, 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; + + 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; + /* scan 7 bit */ + BUFFER_ADD = 0x6; + /* TMS data bits */ + if (ir_scan) + { + BUFFER_ADD = TAP_MOVE(cur_state, TAP_SI); + cur_state = TAP_SI; + } + else + { + BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD); + cur_state = TAP_SD; + } + //DEBUG("added TMS scan (no read)"); + } + + /* 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); + 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) + { + 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]; + } + + 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; + } + 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) + { + 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; + else + last_bit = 0; + + /* process remaining bits but the last one */ + if (bits_left > 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]; + + if (type != SCAN_OUT) + thisrun_read += 2; + } + + if (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; + } + 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; + } + + 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; + + if (type == SCAN_IN) /* only from device to host */ + { + /* complete bytes */ + 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 += num_bytes + (CEIL(num_bytes, 65536)) * 3; + /* remaining bits -1 (up to 7) */ + predicted_size += ((scan_size - 1) % 8) ? 3 : 0; + } + + return predicted_size; +} + +int ft2232_predict_scan_in(int scan_size, enum scan_type type) +{ + int predicted_size = 0; + + if (type != SCAN_OUT) + { + /* complete bytes */ + predicted_size += (CEIL(scan_size, 8) > 1) ? (CEIL(scan_size, 8) - 1) : 0; + /* remaining bits - 1 */ + predicted_size += ((scan_size - 1) % 8) ? 1 : 0; + /* last bit (from TMS scan) */ + predicted_size += 1; + } + + //DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size); + + return predicted_size; +} + +void usbjtag_reset(int trst, int srst) +{ + if (trst == 1) + { + cur_state = TAP_TLR; + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + low_direction |= nTRSTnOE; /* switch to output pin (output is low) */ + else + low_output &= ~nTRST; /* switch output low */ + } + else if (trst == 0) + { + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + low_direction &= ~nTRSTnOE; /* switch to input pin (high-Z + internal and external pullup) */ + else + low_output |= nTRST; /* switch output high */ + } + + if (srst == 1) + { + if (jtag_reset_config & RESET_SRST_PUSH_PULL) + low_output &= ~nSRST; /* switch output low */ + else + low_direction |= nSRSTnOE; /* switch to output pin (output is low) */ + } + else if (srst == 0) + { + if (jtag_reset_config & RESET_SRST_PUSH_PULL) + low_output |= nSRST; /* switch output high */ + else + low_direction &= ~nSRSTnOE; /* switch to input pin (high-Z) */ + } + + /* command "set data bits low byte" */ + BUFFER_ADD = 0x80; + BUFFER_ADD = low_output; + BUFFER_ADD = low_direction; + +} + +void jtagkey_reset(int trst, int srst) +{ + if (trst == 1) + { + cur_state = TAP_TLR; + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + high_output &= ~nTRSTnOE; + else + high_output &= ~nTRST; + } + else if (trst == 0) + { + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + high_output |= nTRSTnOE; + else + high_output |= nTRST; + } + + if (srst == 1) + { + if (jtag_reset_config & RESET_SRST_PUSH_PULL) + high_output &= ~nSRST; + else + high_output &= ~nSRSTnOE; + } + else if (srst == 0) + { + if (jtag_reset_config & RESET_SRST_PUSH_PULL) + high_output |= nSRST; + else + high_output |= nSRSTnOE; + } + + /* command "set data bits high byte" */ + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; + DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); +} + +void olimex_jtag_reset(int trst, int srst) +{ + if (trst == 1) + { + cur_state = TAP_TLR; + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + high_output &= ~nTRSTnOE; + else + high_output &= ~nTRST; + } + else if (trst == 0) + { + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + high_output |= nTRSTnOE; + else + high_output |= nTRST; + } + + if (srst == 1) + { + high_output |= nSRST; + } + else if (srst == 0) + { + high_output &= ~nSRST; + } + + /* command "set data bits high byte" */ + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; + DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); +} + +void flyswatter_reset(int trst, int srst) +{ + if (trst == 1) + { + cur_state = TAP_TLR; + low_output &= ~nTRST; + } + else if (trst == 0) + { + low_output |= nTRST; + } + + if (srst == 1) + { + low_output |= nSRST; + } + else if (srst == 0) + { + low_output &= ~nSRST; + } + + /* command "set data bits low byte" */ + BUFFER_ADD = 0x80; + BUFFER_ADD = low_output; + BUFFER_ADD = low_direction; + DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction); +} + +void turtle_reset(int trst, int srst) +{ + trst = trst; + + if (srst == 1) + { + low_output |= nSRST; + } + else if (srst == 0) + { + low_output &= ~nSRST; + } + + /* command "set data bits low byte" */ + BUFFER_ADD = 0x80; + BUFFER_ADD = low_output; + BUFFER_ADD = low_direction; + DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", srst, low_output, low_direction); +} + +void comstick_reset(int trst, int srst) +{ + if (trst == 1) + { + cur_state = TAP_TLR; + high_output &= ~nTRST; + } + else if (trst == 0) + { + high_output |= nTRST; + } + + if (srst == 1) + { + high_output &= ~nSRST; + } + else if (srst == 0) + { + high_output |= nSRST; + } + + /* command "set data bits high byte" */ + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; + DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); +} + +void stm32stick_reset(int trst, int srst) +{ + if (trst == 1) + { + cur_state = TAP_TLR; + high_output &= ~nTRST; + } + else if (trst == 0) + { + high_output |= nTRST; + } + + if (srst == 1) + { + low_output &= ~nSRST; + } + else if (srst == 0) + { + low_output |= nSRST; + } + + /* command "set data bits low byte" */ + BUFFER_ADD = 0x80; + BUFFER_ADD = low_output; + BUFFER_ADD = low_direction; + + /* command "set data bits high byte" */ + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; + DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction); +} + +int ft2232_execute_queue() +{ + jtag_command_t *cmd = jtag_command_queue; /* currently processed command */ + jtag_command_t *first_unsent = cmd; /* next command that has to be sent */ + u8 *buffer; + int scan_size; /* size of IR or DR scan */ + enum scan_type type; + int i; + int predicted_size = 0; + int require_send = 0; + int retval; + + /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check + * that wasn't handled by a caller-provided error handler + */ + retval = ERROR_OK; + + ft2232_buffer_size = 0; + ft2232_expect_read = 0; + + /* blink, if the current layout has that feature */ + if (layout->blink) + layout->blink(); + + while (cmd) + { + switch(cmd->type) + { + case JTAG_END_STATE: + if (cmd->cmd.end_state->end_state != -1) + ft2232_end_state(cmd->cmd.end_state->end_state); + break; + case JTAG_RESET: + /* only send the maximum buffer size that FT2232C can handle */ + predicted_size = 3; + if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) + { + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + require_send = 0; + first_unsent = cmd; + } + + layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); + require_send = 1; + +#ifdef _DEBUG_JTAG_IO_ + DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); +#endif + break; + case JTAG_RUNTEST: + /* only send the maximum buffer size that FT2232C can handle */ + predicted_size = 0; + if (cur_state != TAP_RTI) + predicted_size += 3; + predicted_size += 3 * CEIL(cmd->cmd.runtest->num_cycles, 7); + if ((cmd->cmd.runtest->end_state != -1) && (cmd->cmd.runtest->end_state != TAP_RTI)) + predicted_size += 3; + if ((cmd->cmd.runtest->end_state == -1) && (end_state != TAP_RTI)) + predicted_size += 3; + if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) + { + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + require_send = 0; + first_unsent = cmd; + } + if (cur_state != TAP_RTI) + { + /* 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_RTI); + cur_state = TAP_RTI; + require_send = 1; + } + i = cmd->cmd.runtest->num_cycles; + while (i > 0) + { + /* command "Clock Data to TMS/CS Pin (no Read)" */ + BUFFER_ADD = 0x4b; + /* scan 7 bit */ + BUFFER_ADD = (i > 7) ? 6 : (i - 1); + /* TMS data bits */ + BUFFER_ADD = 0x0; + cur_state = TAP_RTI; + i -= (i > 7) ? 7 : i; + //DEBUG("added TMS scan (no read)"); + } + if (cmd->cmd.runtest->end_state != -1) + ft2232_end_state(cmd->cmd.runtest->end_state); + if (cur_state != end_state) + { + /* 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, end_state); + cur_state = end_state; + //DEBUG("added TMS scan (no read)"); + } + require_send = 1; +#ifdef _DEBUG_JTAG_IO_ + DEBUG("runtest: %i, end in %i", cmd->cmd.runtest->num_cycles, end_state); +#endif + break; + case JTAG_STATEMOVE: + /* only send the maximum buffer size that FT2232C can handle */ + predicted_size = 3; + if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) + { + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + require_send = 0; + first_unsent = cmd; + } + if (cmd->cmd.statemove->end_state != -1) + ft2232_end_state(cmd->cmd.statemove->end_state); + /* 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, end_state); + //DEBUG("added TMS scan (no read)"); + cur_state = end_state; + require_send = 1; +#ifdef _DEBUG_JTAG_IO_ + DEBUG("statemove: %i", end_state); +#endif + break; + case JTAG_PATHMOVE: + /* only send the maximum buffer size that FT2232C can handle */ + predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7); + if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) + { + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + require_send = 0; + first_unsent = cmd; + } + ft2232_add_pathmove(cmd->cmd.pathmove); + require_send = 1; +#ifdef _DEBUG_JTAG_IO_ + DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); +#endif + break; + case JTAG_SCAN: + 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 ((predicted_size + 1) > FT2232_BUFFER_SIZE) + { + DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)"); + /* unsent commands before this */ + if (first_unsent != cmd) + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + + /* 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("ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)", first_unsent, cmd); + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + require_send = 0; + first_unsent = cmd; + } + ft2232_expect_read += ft2232_predict_scan_in(scan_size, type); + //DEBUG("new read size: %i", ft2232_expect_read); + if (cmd->cmd.scan->end_state != -1) + ft2232_end_state(cmd->cmd.scan->end_state); + ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); + require_send = 1; + if (buffer) + free(buffer); +#ifdef _DEBUG_JTAG_IO_ + DEBUG("%s scan, %i bit, end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, end_state); +#endif + break; + case JTAG_SLEEP: + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + first_unsent = cmd->next; + jtag_sleep(cmd->cmd.sleep->us); +#ifdef _DEBUG_JTAG_IO_ + DEBUG("sleep %i usec", cmd->cmd.sleep->us); +#endif + break; + default: + ERROR("BUG: unknown JTAG command type encountered"); + exit(-1); + } + cmd = cmd->next; + } + + if (require_send > 0) + if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) + retval = ERROR_JTAG_QUEUE_FAILED; + + return retval; +} + +#if BUILD_FT2232_FTD2XX == 1 +static int ft2232_init_ftd2xx(u16 vid, u16 pid, int more, int *try_more) +{ + FT_STATUS status; + DWORD openex_flags = 0; + char *openex_string = NULL; + u8 latency_timer; + + DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", + ft2232_layout, vid, pid); + +#if IS_WIN32 == 0 + /* Add non-standard Vid/Pid to the linux driver */ + if ((status = FT_SetVIDPID(vid, pid)) != FT_OK) + { + WARNING("couldn't add %4.4x:%4.4x", + vid, pid); + } +#endif + + if (ft2232_device_desc && ft2232_serial) + { + WARNING("can't open by device description and serial number, giving precedence to serial"); + ft2232_device_desc = NULL; + } + + if (ft2232_device_desc) + { + openex_string = ft2232_device_desc; + openex_flags = FT_OPEN_BY_DESCRIPTION; + } + else if (ft2232_serial) + { + openex_string = ft2232_serial; + openex_flags = FT_OPEN_BY_SERIAL_NUMBER; + } + else + { + ERROR("neither device description nor serial number specified"); + ERROR("please add \"ft2232_device_desc \" or \"ft2232_serial \" to your .cfg file"); + + return ERROR_JTAG_INIT_FAILED; + } + + if ((status = FT_OpenEx(openex_string, openex_flags, &ftdih)) != FT_OK) + { + DWORD num_devices; + + if (more) { + WARNING("unable to open ftdi device (trying more): %lu", + status); + *try_more = 1; + return ERROR_JTAG_INIT_FAILED; + } + ERROR("unable to open ftdi device: %lu", status); + status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); + if (status == FT_OK) + { + char **desc_array = malloc(sizeof(char*) * (num_devices + 1)); + int i; + + for (i = 0; i < num_devices; i++) + desc_array[i] = malloc(64); + desc_array[num_devices] = NULL; + + status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags); + + if (status == FT_OK) + { + ERROR("ListDevices: %lu\n", num_devices); + for (i = 0; i < num_devices; i++) + ERROR("%i: %s", i, desc_array[i]); + } + + for (i = 0; i < num_devices; i++) + free(desc_array[i]); + free(desc_array); + } + else + { + ERROR("ListDevices: NONE\n"); + } + return ERROR_JTAG_INIT_FAILED; + } + + if ((status = FT_SetLatencyTimer(ftdih, ft2232_latency)) != FT_OK) + { + ERROR("unable to set latency timer: %lu", status); + return ERROR_JTAG_INIT_FAILED; + } + + if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK) + { + ERROR("unable to get latency timer: %lu", status); + return ERROR_JTAG_INIT_FAILED; + } + else + { + DEBUG("current latency timer: %i", latency_timer); + } + + if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK) + { + ERROR("unable to set timeouts: %lu", status); + return ERROR_JTAG_INIT_FAILED; + } + + if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK) + { + ERROR("unable to enable bit i/o mode: %lu", status); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +static int ft2232_purge_ftd2xx(void) +{ + FT_STATUS status; + + if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK) + { + ERROR("error purging ftd2xx device: %lu", status); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} +#endif /* BUILD_FT2232_FTD2XX == 1 */ + +#if BUILD_FT2232_LIBFTDI == 1 +static int ft2232_init_libftdi(u16 vid, u16 pid, int more, int *try_more) +{ + u8 latency_timer; + + DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)", + ft2232_layout, vid, pid); + + if (ftdi_init(&ftdic) < 0) + return ERROR_JTAG_INIT_FAILED; + + /* context, vendor id, product id */ + if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc, + ft2232_serial) < 0) { + if (more) + WARNING("unable to open ftdi device (trying more): %s", + ftdic.error_str); + else + ERROR("unable to open ftdi device: %s", ftdic.error_str); + *try_more = 1; + return ERROR_JTAG_INIT_FAILED; + } + + if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0) + { + ERROR("unable to select FT2232 channel A: %s", ftdic.error_str); + return ERROR_JTAG_INIT_FAILED; + } + + if (ftdi_usb_reset(&ftdic) < 0) + { + ERROR("unable to reset ftdi device"); + return ERROR_JTAG_INIT_FAILED; + } + + if (ftdi_set_latency_timer(&ftdic, ft2232_latency) < 0) + { + ERROR("unable to set latency timer"); + return ERROR_JTAG_INIT_FAILED; + } + + if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) + { + ERROR("unable to get latency timer"); + return ERROR_JTAG_INIT_FAILED; + } + else + { + DEBUG("current latency timer: %i", latency_timer); + } + + ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */ + + return ERROR_OK; +} + +static int ft2232_purge_libftdi(void) +{ + if (ftdi_usb_purge_buffers(&ftdic) < 0) + { + ERROR("ftdi_purge_buffers: %s", ftdic.error_str); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} +#endif /* BUILD_FT2232_LIBFTDI == 1 */ + +int ft2232_init(void) +{ + u8 buf[1]; + int retval; + u32 bytes_written; + ft2232_layout_t *cur_layout = ft2232_layouts; + int i; + + if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0)) + { + ft2232_layout = "usbjtag"; + WARNING("No ft2232 layout specified, using default 'usbjtag'"); + } + + while (cur_layout->name) + { + if (strcmp(cur_layout->name, ft2232_layout) == 0) + { + layout = cur_layout; + break; + } + cur_layout++; + } + + if (!layout) + { + ERROR("No matching layout found for %s", ft2232_layout); + return ERROR_JTAG_INIT_FAILED; + } + + for (i = 0; 1; i++) { + /* + * "more indicates that there are more IDs to try, so we should + * not print an error for an ID mismatch (but for anything + * else, we should). + * + * try_more indicates that the error code returned indicates an + * ID mismatch (and nothing else) and that we should proceeed + * with the next ID pair. + */ + int more = ft2232_vid[i+1] || ft2232_pid[i+1]; + int try_more = 0; + +#if BUILD_FT2232_FTD2XX == 1 + retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i], + more, &try_more); +#elif BUILD_FT2232_LIBFTDI == 1 + retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i], + more, &try_more); +#endif + if (retval >= 0) + break; + if (!more || !try_more) + return retval; + } + + ft2232_buffer_size = 0; + ft2232_buffer = malloc(FT2232_BUFFER_SIZE); + + if (layout->init() != ERROR_OK) + return ERROR_JTAG_INIT_FAILED; + + ft2232_speed(jtag_speed); + + buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */ + if (((retval = ft2232_write(buf, 1, &bytes_written)) != ERROR_OK) || (bytes_written != 1)) + { + ERROR("couldn't write to FT2232 to disable loopback"); + return ERROR_JTAG_INIT_FAILED; + } + +#if BUILD_FT2232_FTD2XX == 1 + return ft2232_purge_ftd2xx(); +#elif BUILD_FT2232_LIBFTDI == 1 + return ft2232_purge_libftdi(); +#endif + + return ERROR_OK; +} + +int usbjtag_init(void) +{ + u8 buf[3]; + u32 bytes_written; + + low_output = 0x08; + low_direction = 0x0b; + + if (strcmp(ft2232_layout, "usbjtag") == 0) + { + nTRST = 0x10; + nTRSTnOE = 0x10; + nSRST = 0x40; + nSRSTnOE = 0x40; + } + else if (strcmp(ft2232_layout, "signalyzer") == 0) + { + nTRST = 0x10; + nTRSTnOE = 0x10; + nSRST = 0x20; + nSRSTnOE = 0x20; + } + else if (strcmp(ft2232_layout, "evb_lm3s811") == 0) + { + nTRST = 0x0; + nTRSTnOE = 0x00; + nSRST = 0x20; + nSRSTnOE = 0x20; + low_output = 0x88; + low_direction = 0x8b; + } + else + { + ERROR("BUG: usbjtag_init called for unknown layout '%s'", ft2232_layout); + return ERROR_JTAG_INIT_FAILED; + } + + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + { + low_direction &= ~nTRSTnOE; /* nTRST input */ + low_output &= ~nTRST; /* nTRST = 0 */ + } + else + { + low_direction |= nTRSTnOE; /* nTRST output */ + low_output |= nTRST; /* nTRST = 1 */ + } + + if (jtag_reset_config & RESET_SRST_PUSH_PULL) + { + low_direction |= nSRSTnOE; /* nSRST output */ + low_output |= nSRST; /* nSRST = 1 */ + } + else + { + low_direction &= ~nSRSTnOE; /* nSRST input */ + low_output &= ~nSRST; /* nSRST = 0 */ + } + + /* initialize low byte for jtag */ + buf[0] = 0x80; /* command "set data bits low byte" */ + buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, xRST high) */ + buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in */ + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'USBJTAG' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +int jtagkey_init(void) +{ + u8 buf[3]; + u32 bytes_written; + + low_output = 0x08; + low_direction = 0x1b; + + /* initialize low byte for jtag */ + buf[0] = 0x80; /* command "set data bits low byte" */ + buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ + buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + if (strcmp(layout->name, "jtagkey") == 0) + { + nTRST = 0x01; + nTRSTnOE = 0x4; + nSRST = 0x02; + nSRSTnOE = 0x08; + } + else if ((strcmp(layout->name, "jtagkey_prototype_v1") == 0) || + (strcmp(layout->name, "oocdlink") == 0)) + { + nTRST = 0x02; + nTRSTnOE = 0x1; + nSRST = 0x08; + nSRSTnOE = 0x04; + } + else + { + ERROR("BUG: jtagkey_init called for non jtagkey layout"); + exit(-1); + } + + high_output = 0x0; + high_direction = 0x0f; + + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + { + high_output |= nTRSTnOE; + high_output &= ~nTRST; + } + else + { + high_output &= ~nTRSTnOE; + high_output |= nTRST; + } + + if (jtag_reset_config & RESET_SRST_PUSH_PULL) + { + high_output &= ~nSRSTnOE; + high_output |= nSRST; + } + else + { + high_output |= nSRSTnOE; + high_output &= ~nSRST; + } + + /* initialize high port */ + buf[0] = 0x82; /* command "set data bits high byte" */ + buf[1] = high_output; /* value */ + buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +int olimex_jtag_init(void) +{ + u8 buf[3]; + u32 bytes_written; + + low_output = 0x08; + low_direction = 0x1b; + + /* initialize low byte for jtag */ + buf[0] = 0x80; /* command "set data bits low byte" */ + buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ + buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nTRST = 0x01; + nTRSTnOE = 0x4; + nSRST = 0x02; + nSRSTnOE = 0x00; /* no output enable for nSRST */ + + high_output = 0x0; + high_direction = 0x0f; + + if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) + { + high_output |= nTRSTnOE; + high_output &= ~nTRST; + } + else + { + high_output &= ~nTRSTnOE; + high_output |= nTRST; + } + + if (jtag_reset_config & RESET_SRST_PUSH_PULL) + { + ERROR("can't set nSRST to push-pull on the Olimex ARM-USB-OCD"); + } + else + { + high_output &= ~nSRST; + } + + /* turn red LED on */ + high_output |= 0x08; + + /* initialize high port */ + buf[0] = 0x82; /* command "set data bits high byte" */ + buf[1] = high_output; /* value */ + buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +int flyswatter_init(void) +{ + u8 buf[3]; + u32 bytes_written; + + low_output = 0x18; + low_direction = 0xfb; + + /* initialize low byte for jtag */ + buf[0] = 0x80; /* command "set data bits low byte" */ + buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ + buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE[12]=out, n[ST]srst=out */ + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nTRST = 0x10; + nTRSTnOE = 0x0; /* not output enable for nTRST */ + nSRST = 0x20; + nSRSTnOE = 0x00; /* no output enable for nSRST */ + + high_output = 0x00; + high_direction = 0x0c; + + /* turn red LED1 on, LED2 off */ + high_output |= 0x08; + + /* initialize high port */ + buf[0] = 0x82; /* command "set data bits high byte" */ + buf[1] = high_output; /* value */ + buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */ + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +int turtle_init(void) +{ + u8 buf[3]; + u32 bytes_written; + + low_output = 0x08; + low_direction = 0x5b; + + /* initialize low byte for jtag */ + buf[0] = 0x80; /* command "set data bits low byte" */ + buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ + buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nSRST = 0x40; + + high_output = 0x00; + high_direction = 0x0C; + + /* initialize high port */ + buf[0] = 0x82; /* command "set data bits high byte" */ + buf[1] = high_output; + buf[2] = high_direction; + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +int comstick_init(void) +{ + u8 buf[3]; + u32 bytes_written; + + low_output = 0x08; + low_direction = 0x0b; + + /* initialize low byte for jtag */ + buf[0] = 0x80; /* command "set data bits low byte" */ + buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ + buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'comstick' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nTRST = 0x01; + nTRSTnOE = 0x00; /* no output enable for nTRST */ + nSRST = 0x02; + nSRSTnOE = 0x00; /* no output enable for nSRST */ + + high_output = 0x03; + high_direction = 0x03; + + /* initialize high port */ + buf[0] = 0x82; /* command "set data bits high byte" */ + buf[1] = high_output; + buf[2] = high_direction; + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'comstick' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +int stm32stick_init(void) +{ + u8 buf[3]; + u32 bytes_written; + + low_output = 0x88; + low_direction = 0x8b; + + /* initialize low byte for jtag */ + buf[0] = 0x80; /* command "set data bits low byte" */ + buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */ + buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */ + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + nTRST = 0x01; + nTRSTnOE = 0x00; /* no output enable for nTRST */ + nSRST = 0x80; + nSRSTnOE = 0x00; /* no output enable for nSRST */ + + high_output = 0x01; + high_direction = 0x03; + + /* initialize high port */ + buf[0] = 0x82; /* command "set data bits high byte" */ + buf[1] = high_output; + buf[2] = high_direction; + DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); + + if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) + { + ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); + return ERROR_JTAG_INIT_FAILED; + } + + return ERROR_OK; +} + +void olimex_jtag_blink(void) +{ + /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 + * ACBUS3 is bit 3 of the GPIOH port + */ + if (high_output & 0x08) + { + /* set port pin high */ + high_output &= 0x07; + } + else + { + /* set port pin low */ + high_output |= 0x08; + } + + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; +} + +void turtle_jtag_blink(void) +{ + /* + * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3 + */ + if (high_output & 0x08) + { + high_output = 0x04; + } + else + { + high_output = 0x08; + } + + BUFFER_ADD = 0x82; + BUFFER_ADD = high_output; + BUFFER_ADD = high_direction; +} + + +int ft2232_quit(void) +{ +#if BUILD_FT2232_FTD2XX == 1 + FT_STATUS status; + + status = FT_Close(ftdih); +#elif BUILD_FT2232_LIBFTDI == 1 + ftdi_disable_bitbang(&ftdic); + + ftdi_usb_close(&ftdic); + + ftdi_deinit(&ftdic); +#endif + + free(ft2232_buffer); + ft2232_buffer = NULL; + + return ERROR_OK; +} + +int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc == 1) + { + ft2232_device_desc = strdup(args[0]); + } + else + { + ERROR("expected exactly one argument to ft2232_device_desc "); + } + + return ERROR_OK; +} + +int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc == 1) + { + ft2232_serial = strdup(args[0]); + } + else + { + ERROR("expected exactly one argument to ft2232_serial "); + } + + return ERROR_OK; +} + +int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc == 0) + return ERROR_OK; + + ft2232_layout = malloc(strlen(args[0]) + 1); + strcpy(ft2232_layout, args[0]); + + return ERROR_OK; +} + +int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + int i; + + if (argc > MAX_USB_IDS*2) { + WARNING("ignoring extra IDs in ft2232_vid_pid " + "(maximum is %d pairs)", MAX_USB_IDS); + argc = MAX_USB_IDS*2; + } + if (argc < 2 || (argc & 1)) + { + WARNING("incomplete ft2232_vid_pid configuration directive"); + if (argc < 2) + return ERROR_OK; + } + + for (i = 0; i+1 < argc; i += 2) { + ft2232_vid[i >> 1] = strtol(args[i], NULL, 0); + ft2232_pid[i >> 1] = strtol(args[i+1], NULL, 0); + } + /* + * Explicitly terminate, in case there are multiples instances of + * ft2232_vid_pid. + */ + ft2232_vid[i >> 1] = ft2232_pid[i >> 1] = 0; + + return ERROR_OK; +} + +int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (argc == 1) + { + ft2232_latency = atoi(args[0]); + } + else + { + ERROR("expected exactly one argument to ft2232_latency "); + } + + return ERROR_OK; +} + + diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c index 16012887..f4c4dc4a 100644 --- a/src/xsvf/xsvf.c +++ b/src/xsvf/xsvf.c @@ -1,504 +1,504 @@ -/*************************************************************************** - * Copyright (C) 2005 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 "xsvf.h" - -#include "jtag.h" -#include "command.h" -#include "log.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define XSTATE_MAX_PATH (12) - -int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); - -int xsvf_fd = 0; - -u8 *dr_out_buf; /* from host to device (TDI) */ -u8 *dr_in_buf; /* from device to host (TDO) */ -u8 *dr_in_mask; - -int xsdrsize = 0; -int xruntest = 0; /* number of TCK cycles / microseconds */ -int xrepeat = 0x20; /* number of XC9500 retries */ - -int xendir = 0; -int xenddr = 0; - -enum tap_state xsvf_to_tap[] = -{ - TAP_TLR, TAP_RTI, - TAP_SDS, TAP_CD, TAP_SD, TAP_E1D, TAP_PD, TAP_E2D, TAP_UD, - TAP_SIS, TAP_CI, TAP_SI, TAP_E1I, TAP_PI, TAP_E2I, TAP_UI, -}; - -int tap_to_xsvf[] = -{ - 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x9, 0xa, 0xb, 0xc, 0xe, 0xf -}; - -int xsvf_register_commands(struct command_context_s *cmd_ctx) -{ - register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command, - COMMAND_EXEC, "run xsvf "); - - return ERROR_OK; -} - -int xsvf_read_buffer(int num_bits, int fd, u8* buf) -{ - int num_bytes; - - for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--) - { - if (read(fd, buf + num_bytes - 1, 1) < 0) - return ERROR_XSVF_EOF; - } - - return ERROR_OK; -} - -int xsvf_read_xstates(int fd, enum tap_state *path, int max_path, int *path_len) -{ - char c; - unsigned char uc; - - while ((read(fd, &c, 1) > 0) && (c == 0x12)) - { - if (*path_len > max_path) - { - WARNING("XSTATE path longer than max_path"); - break; - } - if (read(fd, &uc, 1) < 0) - { - return ERROR_XSVF_EOF; - } - path[(*path_len)++] = xsvf_to_tap[uc]; - } - - lseek(fd, -1, SEEK_CUR); - - return ERROR_OK; -} - -int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - char c; - u8 buf4[4], buf2[2]; - unsigned char uc, uc2; - unsigned int ui; - unsigned short us; - - int do_abort = 0; - int unsupported = 0; - int tdo_mismatch = 0; - - int runtest_requires_tck = 0; - - int device = -1; /* use -1 to indicate a "plain" xsvf file which accounts for additional devices in the scan chain, otherwise the device that should be affected */ - - if (argc < 2) - { - command_print(cmd_ctx, "usage: xsvf "); - return ERROR_OK; - } - - if (strcmp(args[0], "plain") != 0) - { - device = strtoul(args[0], NULL, 0); - } - - if ((xsvf_fd = open(args[1], O_RDONLY)) < 0) - { - command_print(cmd_ctx, "file %s not found", args[0]); - return ERROR_OK; - } - - if ((argc > 2) && (strcmp(args[2], "virt2") == 0)) - { - runtest_requires_tck = 1; - } - - while (read(xsvf_fd, &c, 1) > 0) - { - switch (c) - { - case 0x00: /* XCOMPLETE */ - DEBUG("XCOMPLETE"); - if (jtag_execute_queue() != ERROR_OK) - { - tdo_mismatch = 1; - break; - } - break; - case 0x01: /* XTDOMASK */ - DEBUG("XTDOMASK"); - if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK)) - do_abort = 1; - break; - case 0x02: /* XSIR */ - DEBUG("XSIR"); - if (read(xsvf_fd, &c, 1) < 0) - do_abort = 1; - else - { - u8 *ir_buf = malloc((c + 7) / 8); - if (xsvf_read_buffer(c, xsvf_fd, ir_buf) != ERROR_OK) - do_abort = 1; - else - { - scan_field_t field; - field.device = device; - field.num_bits = c; - field.out_value = ir_buf; - field.out_mask = NULL; - field.in_value = NULL; - field.in_check_value = NULL; - field.in_check_mask = NULL; - field.in_handler = NULL; - field.in_handler_priv = NULL; - if (device == -1) - jtag_add_plain_ir_scan(1, &field, TAP_PI, NULL); - else - jtag_add_ir_scan(1, &field, TAP_PI, NULL); - if (jtag_execute_queue() != ERROR_OK) - { - tdo_mismatch = 1; - free(ir_buf); - break; - } - if (xruntest) - { - if (runtest_requires_tck) - jtag_add_runtest(xruntest, xsvf_to_tap[xendir]); - else - { - jtag_add_statemove(TAP_RTI); - jtag_add_sleep(xruntest); - jtag_add_statemove(xsvf_to_tap[xendir]); - } - } - else if (xendir != 0xd) /* Pause-IR */ - jtag_add_statemove(xsvf_to_tap[xendir]); - } - free(ir_buf); - } - break; - case 0x03: /* XSDR */ - DEBUG("XSDR"); - if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK) - do_abort = 1; - else - { - scan_field_t field; - field.device = device; - field.num_bits = xsdrsize; - field.out_value = dr_out_buf; - field.out_mask = NULL; - field.in_value = NULL; - jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL); - if (device == -1) - jtag_add_plain_dr_scan(1, &field, TAP_PD, NULL); - else - jtag_add_dr_scan(1, &field, TAP_PD, NULL); - if (jtag_execute_queue() != ERROR_OK) - { - tdo_mismatch = 1; - break; - } - if (xruntest) - { - if (runtest_requires_tck) - jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]); - else - { - jtag_add_statemove(TAP_RTI); - jtag_add_sleep(xruntest); - jtag_add_statemove(xsvf_to_tap[xenddr]); - } - } - else if (xendir != 0x6) /* Pause-DR */ - jtag_add_statemove(xsvf_to_tap[xenddr]); - } - break; - case 0x04: /* XRUNTEST */ - DEBUG("XRUNTEST"); - if (read(xsvf_fd, buf4, 4) < 0) - do_abort = 1; - else - { - xruntest = be_to_h_u32(buf4); - } - break; - case 0x07: /* XREPEAT */ - DEBUG("XREPEAT"); - if (read(xsvf_fd, &c, 1) < 0) - do_abort = 1; - else - { - xrepeat = c; - } - break; - case 0x08: /* XSDRSIZE */ - DEBUG("XSDRSIZE"); - if (read(xsvf_fd, buf4, 4) < 0) - do_abort = 1; - else - { - xsdrsize = be_to_h_u32(buf4); - free(dr_out_buf); - free(dr_in_buf); - free(dr_in_mask); - dr_out_buf = malloc((xsdrsize + 7) / 8); - dr_in_buf = malloc((xsdrsize + 7) / 8); - dr_in_mask = malloc((xsdrsize + 7) / 8); - } - break; - case 0x09: /* XSDRTDO */ - DEBUG("XSDRTDO"); - if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK) - do_abort = 1; - else - { - if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK) - do_abort = 1; - else - { - scan_field_t field; - field.device = device; - field.num_bits = xsdrsize; - field.out_value = dr_out_buf; - field.out_mask = NULL; - field.in_value = NULL; - jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL); - if (device == -1) - jtag_add_plain_dr_scan(1, &field, TAP_PD, NULL); - else - jtag_add_dr_scan(1, &field, TAP_PD, NULL); - if (jtag_execute_queue() != ERROR_OK) - { - tdo_mismatch = 1; - break; - } - if (xruntest) - { - if (runtest_requires_tck) - jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]); - else - { - jtag_add_statemove(TAP_RTI); - jtag_add_sleep(xruntest); - jtag_add_statemove(xsvf_to_tap[xenddr]); - } - } - else if (xendir != 0x6) /* Pause-DR */ - jtag_add_statemove(xsvf_to_tap[xenddr]); - } - } - break; - case 0x0a: /* XSETDRMASKS */ - printf("unsupported XSETSDRMASKS\n"); - unsupported = 1; - break; - case 0x0b: /* XSDRINC */ - printf("unsupported XSDRINC\n"); - unsupported = 1; - break; - case 0x0c: /* XSDRB */ - unsupported = 1; - break; - case 0x0d: /* XSDRC */ - unsupported = 1; - break; - case 0x0e: /* XSDRE */ - unsupported = 1; - break; - case 0x0f: /* XSDRTDOB */ - unsupported = 1; - break; - case 0x10: /* XSDRTDOB */ - unsupported = 1; - break; - case 0x11: /* XSDRTDOB */ - unsupported = 1; - break; - case 0x12: /* XSTATE */ - DEBUG("XSTATE"); - if (read(xsvf_fd, &uc, 1) < 0) - do_abort = 1; - else - { - enum tap_state *path = calloc(XSTATE_MAX_PATH, 4); - int path_len = 1; - path[0] = xsvf_to_tap[uc]; - if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK) - do_abort = 1; - else - { - jtag_add_pathmove(path_len, path); - } - free(path); - } - break; - case 0x13: /* XENDIR */ - DEBUG("XENDIR"); - if (read(xsvf_fd, &c, 1) < 0) - do_abort = 1; - else - { - if (c == 0) - xendir = 1; - else if (c == 1) - xendir = 0xd; - else - { - ERROR("unknown XENDIR endstate"); - unsupported = 1; - } - } - break; - case 0x14: /* XENDDR */ - DEBUG("XENDDR"); - if (read(xsvf_fd, &c, 1) < 0) - do_abort = 1; - else - { - if (c == 0) - xenddr = 1; - else if (c == 1) - xenddr = 0x6; - else - { - ERROR("unknown XENDDR endstate"); - unsupported = 1; - } - } - break; - case 0x15: /* XSIR2 */ - DEBUG("XSIR2"); - if (read(xsvf_fd, buf2, 2) < 0) - do_abort = 1; - else - { - u8 *ir_buf; - us = be_to_h_u16(buf2); - ir_buf = malloc((us + 7) / 8); - if (xsvf_read_buffer(us, xsvf_fd, ir_buf) != ERROR_OK) - do_abort = 1; - else - { - scan_field_t field; - field.device = device; - field.num_bits = us; - field.out_value = ir_buf; - field.out_mask = NULL; - field.in_value = NULL; - field.in_check_value = NULL; - field.in_check_mask = NULL; - field.in_handler = NULL; - field.in_handler_priv = NULL; - if (device == -1) - jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir], NULL); - else - jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir], NULL); - } - free(ir_buf); - } - break; - case 0x16: /* XCOMMENT */ - do - { - if (read(xsvf_fd, &c, 1) < 0) - { - do_abort = 1; - break; - } - } while (c != 0); - break; - case 0x17: /* XWAIT */ - DEBUG("XWAIT"); - if ((read(xsvf_fd, &uc, 1) < 0) || (read(xsvf_fd, &uc2, 1) < 0) || (read(xsvf_fd, buf4, 4) < 0)) - do_abort = 1; - else - { - jtag_add_statemove(xsvf_to_tap[uc]); - ui = be_to_h_u32(buf4); - jtag_add_sleep(ui); - jtag_add_statemove(xsvf_to_tap[uc2]); - } - break; - default: - printf("unknown xsvf command (0x%2.2x)\n", c); - unsupported = 1; - } - - if (do_abort || unsupported || tdo_mismatch) - break; - } - - if (tdo_mismatch) - { - command_print(cmd_ctx, "TDO mismatch, aborting"); - jtag_cancel_queue(); - return ERROR_OK; - } - - if (unsupported) - { - command_print(cmd_ctx, "unsupported xsvf command encountered, aborting"); - jtag_cancel_queue(); - return ERROR_OK; - } - - if (do_abort) - { - command_print(cmd_ctx, "premature end detected, aborting"); - jtag_cancel_queue(); - return ERROR_OK; - } - - if (dr_out_buf) - free(dr_out_buf); - - if (dr_in_buf) - free(dr_in_buf); - - if (dr_in_mask) - free(dr_in_mask); - - close(xsvf_fd); - - command_print(cmd_ctx, "XSVF file programmed successfully"); - - return ERROR_OK; -} +/*************************************************************************** + * Copyright (C) 2005 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 "xsvf.h" + +#include "jtag.h" +#include "command.h" +#include "log.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define XSTATE_MAX_PATH (12) + +int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); + +int xsvf_fd = 0; + +u8 *dr_out_buf; /* from host to device (TDI) */ +u8 *dr_in_buf; /* from device to host (TDO) */ +u8 *dr_in_mask; + +int xsdrsize = 0; +int xruntest = 0; /* number of TCK cycles / microseconds */ +int xrepeat = 0x20; /* number of XC9500 retries */ + +int xendir = 0; +int xenddr = 0; + +enum tap_state xsvf_to_tap[] = +{ + TAP_TLR, TAP_RTI, + TAP_SDS, TAP_CD, TAP_SD, TAP_E1D, TAP_PD, TAP_E2D, TAP_UD, + TAP_SIS, TAP_CI, TAP_SI, TAP_E1I, TAP_PI, TAP_E2I, TAP_UI, +}; + +int tap_to_xsvf[] = +{ + 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x9, 0xa, 0xb, 0xc, 0xe, 0xf +}; + +int xsvf_register_commands(struct command_context_s *cmd_ctx) +{ + register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command, + COMMAND_EXEC, "run xsvf "); + + return ERROR_OK; +} + +int xsvf_read_buffer(int num_bits, int fd, u8* buf) +{ + int num_bytes; + + for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--) + { + if (read(fd, buf + num_bytes - 1, 1) < 0) + return ERROR_XSVF_EOF; + } + + return ERROR_OK; +} + +int xsvf_read_xstates(int fd, enum tap_state *path, int max_path, int *path_len) +{ + char c; + unsigned char uc; + + while ((read(fd, &c, 1) > 0) && (c == 0x12)) + { + if (*path_len > max_path) + { + WARNING("XSTATE path longer than max_path"); + break; + } + if (read(fd, &uc, 1) < 0) + { + return ERROR_XSVF_EOF; + } + path[(*path_len)++] = xsvf_to_tap[uc]; + } + + lseek(fd, -1, SEEK_CUR); + + return ERROR_OK; +} + +int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + char c; + u8 buf4[4], buf2[2]; + unsigned char uc, uc2; + unsigned int ui; + unsigned short us; + + int do_abort = 0; + int unsupported = 0; + int tdo_mismatch = 0; + + int runtest_requires_tck = 0; + + int device = -1; /* use -1 to indicate a "plain" xsvf file which accounts for additional devices in the scan chain, otherwise the device that should be affected */ + + if (argc < 2) + { + command_print(cmd_ctx, "usage: xsvf "); + return ERROR_OK; + } + + if (strcmp(args[0], "plain") != 0) + { + device = strtoul(args[0], NULL, 0); + } + + if ((xsvf_fd = open(args[1], O_RDONLY)) < 0) + { + command_print(cmd_ctx, "file %s not found", args[0]); + return ERROR_OK; + } + + if ((argc > 2) && (strcmp(args[2], "virt2") == 0)) + { + runtest_requires_tck = 1; + } + + while (read(xsvf_fd, &c, 1) > 0) + { + switch (c) + { + case 0x00: /* XCOMPLETE */ + DEBUG("XCOMPLETE"); + if (jtag_execute_queue() != ERROR_OK) + { + tdo_mismatch = 1; + break; + } + break; + case 0x01: /* XTDOMASK */ + DEBUG("XTDOMASK"); + if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK)) + do_abort = 1; + break; + case 0x02: /* XSIR */ + DEBUG("XSIR"); + if (read(xsvf_fd, &c, 1) < 0) + do_abort = 1; + else + { + u8 *ir_buf = malloc((c + 7) / 8); + if (xsvf_read_buffer(c, xsvf_fd, ir_buf) != ERROR_OK) + do_abort = 1; + else + { + scan_field_t field; + field.device = device; + field.num_bits = c; + field.out_value = ir_buf; + field.out_mask = NULL; + field.in_value = NULL; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = NULL; + field.in_handler_priv = NULL; + if (device == -1) + jtag_add_plain_ir_scan(1, &field, TAP_PI, NULL); + else + jtag_add_ir_scan(1, &field, TAP_PI, NULL); + if (jtag_execute_queue() != ERROR_OK) + { + tdo_mismatch = 1; + free(ir_buf); + break; + } + if (xruntest) + { + if (runtest_requires_tck) + jtag_add_runtest(xruntest, xsvf_to_tap[xendir]); + else + { + jtag_add_statemove(TAP_RTI); + jtag_add_sleep(xruntest); + jtag_add_statemove(xsvf_to_tap[xendir]); + } + } + else if (xendir != 0xd) /* Pause-IR */ + jtag_add_statemove(xsvf_to_tap[xendir]); + } + free(ir_buf); + } + break; + case 0x03: /* XSDR */ + DEBUG("XSDR"); + if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK) + do_abort = 1; + else + { + scan_field_t field; + field.device = device; + field.num_bits = xsdrsize; + field.out_value = dr_out_buf; + field.out_mask = NULL; + field.in_value = NULL; + jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL); + if (device == -1) + jtag_add_plain_dr_scan(1, &field, TAP_PD, NULL); + else + jtag_add_dr_scan(1, &field, TAP_PD, NULL); + if (jtag_execute_queue() != ERROR_OK) + { + tdo_mismatch = 1; + break; + } + if (xruntest) + { + if (runtest_requires_tck) + jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]); + else + { + jtag_add_statemove(TAP_RTI); + jtag_add_sleep(xruntest); + jtag_add_statemove(xsvf_to_tap[xenddr]); + } + } + else if (xendir != 0x6) /* Pause-DR */ + jtag_add_statemove(xsvf_to_tap[xenddr]); + } + break; + case 0x04: /* XRUNTEST */ + DEBUG("XRUNTEST"); + if (read(xsvf_fd, buf4, 4) < 0) + do_abort = 1; + else + { + xruntest = be_to_h_u32(buf4); + } + break; + case 0x07: /* XREPEAT */ + DEBUG("XREPEAT"); + if (read(xsvf_fd, &c, 1) < 0) + do_abort = 1; + else + { + xrepeat = c; + } + break; + case 0x08: /* XSDRSIZE */ + DEBUG("XSDRSIZE"); + if (read(xsvf_fd, buf4, 4) < 0) + do_abort = 1; + else + { + xsdrsize = be_to_h_u32(buf4); + free(dr_out_buf); + free(dr_in_buf); + free(dr_in_mask); + dr_out_buf = malloc((xsdrsize + 7) / 8); + dr_in_buf = malloc((xsdrsize + 7) / 8); + dr_in_mask = malloc((xsdrsize + 7) / 8); + } + break; + case 0x09: /* XSDRTDO */ + DEBUG("XSDRTDO"); + if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK) + do_abort = 1; + else + { + if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK) + do_abort = 1; + else + { + scan_field_t field; + field.device = device; + field.num_bits = xsdrsize; + field.out_value = dr_out_buf; + field.out_mask = NULL; + field.in_value = NULL; + jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL); + if (device == -1) + jtag_add_plain_dr_scan(1, &field, TAP_PD, NULL); + else + jtag_add_dr_scan(1, &field, TAP_PD, NULL); + if (jtag_execute_queue() != ERROR_OK) + { + tdo_mismatch = 1; + break; + } + if (xruntest) + { + if (runtest_requires_tck) + jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]); + else + { + jtag_add_statemove(TAP_RTI); + jtag_add_sleep(xruntest); + jtag_add_statemove(xsvf_to_tap[xenddr]); + } + } + else if (xendir != 0x6) /* Pause-DR */ + jtag_add_statemove(xsvf_to_tap[xenddr]); + } + } + break; + case 0x0a: /* XSETDRMASKS */ + ERROR("unsupported XSETSDRMASKS\n"); + unsupported = 1; + break; + case 0x0b: /* XSDRINC */ + ERROR("unsupported XSDRINC\n"); + unsupported = 1; + break; + case 0x0c: /* XSDRB */ + unsupported = 1; + break; + case 0x0d: /* XSDRC */ + unsupported = 1; + break; + case 0x0e: /* XSDRE */ + unsupported = 1; + break; + case 0x0f: /* XSDRTDOB */ + unsupported = 1; + break; + case 0x10: /* XSDRTDOB */ + unsupported = 1; + break; + case 0x11: /* XSDRTDOB */ + unsupported = 1; + break; + case 0x12: /* XSTATE */ + DEBUG("XSTATE"); + if (read(xsvf_fd, &uc, 1) < 0) + do_abort = 1; + else + { + enum tap_state *path = calloc(XSTATE_MAX_PATH, 4); + int path_len = 1; + path[0] = xsvf_to_tap[uc]; + if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK) + do_abort = 1; + else + { + jtag_add_pathmove(path_len, path); + } + free(path); + } + break; + case 0x13: /* XENDIR */ + DEBUG("XENDIR"); + if (read(xsvf_fd, &c, 1) < 0) + do_abort = 1; + else + { + if (c == 0) + xendir = 1; + else if (c == 1) + xendir = 0xd; + else + { + ERROR("unknown XENDIR endstate"); + unsupported = 1; + } + } + break; + case 0x14: /* XENDDR */ + DEBUG("XENDDR"); + if (read(xsvf_fd, &c, 1) < 0) + do_abort = 1; + else + { + if (c == 0) + xenddr = 1; + else if (c == 1) + xenddr = 0x6; + else + { + ERROR("unknown XENDDR endstate"); + unsupported = 1; + } + } + break; + case 0x15: /* XSIR2 */ + DEBUG("XSIR2"); + if (read(xsvf_fd, buf2, 2) < 0) + do_abort = 1; + else + { + u8 *ir_buf; + us = be_to_h_u16(buf2); + ir_buf = malloc((us + 7) / 8); + if (xsvf_read_buffer(us, xsvf_fd, ir_buf) != ERROR_OK) + do_abort = 1; + else + { + scan_field_t field; + field.device = device; + field.num_bits = us; + field.out_value = ir_buf; + field.out_mask = NULL; + field.in_value = NULL; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = NULL; + field.in_handler_priv = NULL; + if (device == -1) + jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir], NULL); + else + jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir], NULL); + } + free(ir_buf); + } + break; + case 0x16: /* XCOMMENT */ + do + { + if (read(xsvf_fd, &c, 1) < 0) + { + do_abort = 1; + break; + } + } while (c != 0); + break; + case 0x17: /* XWAIT */ + DEBUG("XWAIT"); + if ((read(xsvf_fd, &uc, 1) < 0) || (read(xsvf_fd, &uc2, 1) < 0) || (read(xsvf_fd, buf4, 4) < 0)) + do_abort = 1; + else + { + jtag_add_statemove(xsvf_to_tap[uc]); + ui = be_to_h_u32(buf4); + jtag_add_sleep(ui); + jtag_add_statemove(xsvf_to_tap[uc2]); + } + break; + default: + ERROR("unknown xsvf command (0x%2.2x)\n", c); + unsupported = 1; + } + + if (do_abort || unsupported || tdo_mismatch) + break; + } + + if (tdo_mismatch) + { + command_print(cmd_ctx, "TDO mismatch, aborting"); + jtag_cancel_queue(); + return ERROR_OK; + } + + if (unsupported) + { + command_print(cmd_ctx, "unsupported xsvf command encountered, aborting"); + jtag_cancel_queue(); + return ERROR_OK; + } + + if (do_abort) + { + command_print(cmd_ctx, "premature end detected, aborting"); + jtag_cancel_queue(); + return ERROR_OK; + } + + if (dr_out_buf) + free(dr_out_buf); + + if (dr_in_buf) + free(dr_in_buf); + + if (dr_in_mask) + free(dr_in_mask); + + close(xsvf_fd); + + command_print(cmd_ctx, "XSVF file programmed successfully"); + + return ERROR_OK; +}