jtag: add support for some probes that are mostly compatible with opendous
[openocd.git] / src / jtag / drivers / opendous.c
index 165bec6a08a5bf9507b4d46991b3b4665a2d2334..1343b7f5c00825056d9abf183d1cb25e4a351e8a 100644 (file)
 #include <sys/timeb.h>
 #include <time.h>
 
-#define ESTICK_VID 0x1781
-#define ESTICK_PID 0xC0C0
-
-#define OPENDOUS_VID 0x03EB
-#define OPENDOUS_PID 0x204F
+#define OPENDOUS_MAX_VIDS_PIDS 4
+/* define some probes with similar interface */
+struct opendous_probe {
+       char *name;
+       uint16_t VID[OPENDOUS_MAX_VIDS_PIDS];
+       uint16_t PID[OPENDOUS_MAX_VIDS_PIDS];
+       uint8_t READ_EP;
+       uint8_t WRITE_EP;
+       uint8_t CONTROL_TRANSFER;
+       int BUFFERSIZE;
+};
 
-/* pid could be specified at runtime */
-static uint16_t vids[] = { OPENDOUS_VID, ESTICK_VID, 0 };
-static uint16_t pids[] = { OPENDOUS_PID, ESTICK_PID, 0 };
+static struct opendous_probe opendous_probes[] = {
+       {"usbprog-jtag",        {0x1781, 0},                    {0x0C63, 0},                    0x82, 0x02, 0x00, 510 },
+       {"opendous",            {0x1781, 0x03EB, 0},    {0xC0C0, 0x204F, 0},    0x81, 0x02, 0x00, 360 },
+       {"usbvlab",                     {0x16C0, 0},                    {0x05DC, 0},                    0x81, 0x02, 0x01, 360 },
+       {NULL,                          {0x0000},                               {0x0000},                               0x00, 0x00, 0x00,   0 }
+};
 
-#define OPENDOUS_WRITE_ENDPOINT   0x02
-#define OPENDOUS_READ_ENDPOINT    0x81
+#define OPENDOUS_WRITE_ENDPOINT   (opendous_probe->WRITE_EP)
+#define OPENDOUS_READ_ENDPOINT    (opendous_probe->READ_EP)
 
 static unsigned int opendous_hw_jtag_version = 1;
 
 #define OPENDOUS_USB_TIMEOUT      1000
 
-#define OPENDOUS_USB_BUFFER_SIZE  360
+#define OPENDOUS_USB_BUFFER_SIZE  (opendous_probe->BUFFERSIZE)
 #define OPENDOUS_IN_BUFFER_SIZE   (OPENDOUS_USB_BUFFER_SIZE)
 #define OPENDOUS_OUT_BUFFER_SIZE  (OPENDOUS_USB_BUFFER_SIZE)
 
 /* Global USB buffers */
-static uint8_t usb_in_buffer[OPENDOUS_IN_BUFFER_SIZE];
-static uint8_t usb_out_buffer[OPENDOUS_OUT_BUFFER_SIZE];
+static uint8_t *usb_in_buffer;
+static uint8_t *usb_out_buffer;
 
 /* Constants for OPENDOUS command */
 
 #define OPENDOUS_MAX_SPEED                     66
-#define OPENDOUS_MAX_TAP_TRANSMIT      350     /* even number is easier to handle */
+#define OPENDOUS_MAX_TAP_TRANSMIT      ((opendous_probe->BUFFERSIZE)-10)
 #define OPENDOUS_MAX_INPUT_DATA                (OPENDOUS_MAX_TAP_TRANSMIT*4)
 
+/* TAP */
 #define OPENDOUS_TAP_BUFFER_SIZE 65536
 
+struct pending_scan_result {
+       int first;      /* First bit position in tdo_buffer to read */
+       int length; /* Number of bits to read */
+       struct scan_command *command; /* Corresponding scan command */
+       uint8_t *buffer;
+};
+
+static int pending_scan_results_length;
+static struct pending_scan_result *pending_scan_results_buffer;
+
 #define MAX_PENDING_SCAN_RESULTS (OPENDOUS_MAX_INPUT_DATA)
 
 /* JTAG usb commands */
@@ -84,11 +104,16 @@ static uint8_t usb_out_buffer[OPENDOUS_OUT_BUFFER_SIZE];
 #define JTAG_CMD_SET_SRST_TRST 0x6
 #define JTAG_CMD_READ_CONFIG   0x7
 
+/* usbvlab control transfer */
+#define FUNC_START_BOOTLOADER 30
+#define FUNC_WRITE_DATA       0x50
+#define FUNC_READ_DATA        0x51
+
+static char *opendous_type;
+static struct opendous_probe *opendous_probe;
+
 /* External interface functions */
 static int opendous_execute_queue(void);
-static int opendous_speed(int speed);
-static int opendous_speed_div(int speed, int *khz);
-static int opendous_khz(int khz, int *jtag_speed);
 static int opendous_init(void);
 static int opendous_quit(void);
 
@@ -135,6 +160,22 @@ static struct opendous_jtag *opendous_jtag_handle;
 /***************************************************************************/
 /* External interface implementation */
 
+COMMAND_HANDLER(opendous_handle_opendous_type_command)
+{
+       if (CMD_ARGC == 0)
+               return ERROR_OK;
+
+       /* only if the cable name wasn't overwritten by cmdline */
+       if (opendous_type == NULL) {
+               /* REVISIT first verify that it's listed in cables[] ... */
+               opendous_type = strdup(CMD_ARGV[0]);
+       }
+
+       /* REVISIT it's probably worth returning the current value ... */
+
+       return ERROR_OK;
+}
+
 COMMAND_HANDLER(opendous_handle_opendous_info_command)
 {
        if (opendous_get_version_info() == ERROR_OK) {
@@ -187,6 +228,13 @@ static const struct command_registration opendous_command_handlers[] = {
                .help = "access opendous HW JTAG command version",
                .usage = "[2|3]",
        },
+       {
+               .name = "opendous_type",
+               .handler = &opendous_handle_opendous_type_command,
+               .mode = COMMAND_CONFIG,
+               .help = "set opendous type",
+               .usage = "[usbvlab|usbprog-jtag|opendous]",
+       },
        COMMAND_REGISTRATION_DONE
 };
 
@@ -194,9 +242,6 @@ struct jtag_interface opendous_interface = {
        .name = "opendous",
        .commands = opendous_command_handlers,
        .execute_queue = opendous_execute_queue,
-       .speed = opendous_speed,
-       .speed_div = opendous_speed_div,
-       .khz = opendous_khz,
        .init = opendous_init,
        .quit = opendous_quit,
 };
@@ -276,36 +321,37 @@ static int opendous_execute_queue(void)
        return opendous_tap_execute();
 }
 
-/* Sets speed in kHz. */
-static int opendous_speed(int speed)
+static int opendous_init(void)
 {
-       if (speed <= OPENDOUS_MAX_SPEED) {
-               /* one day... */
-               return ERROR_OK;
-       } else
-               LOG_INFO("Requested speed %dkHz exceeds maximum of %dkHz, ignored", speed, OPENDOUS_MAX_SPEED);
+       int check_cnt;
+       struct opendous_probe *cur_opendous_probe;
 
-       return ERROR_OK;
-}
+       cur_opendous_probe = opendous_probes;
 
-static int opendous_speed_div(int speed, int *khz)
-{
-       *khz = speed;
+       if (opendous_type == NULL) {
+               opendous_type = strdup("opendous");
+               LOG_WARNING("No opendous_type specified, using default 'opendous'");
+       }
 
-       return ERROR_OK;
-}
+       while (cur_opendous_probe->name) {
+               if (strcmp(cur_opendous_probe->name, opendous_type) == 0) {
+                       opendous_probe = cur_opendous_probe;
+                       break;
+               }
+               cur_opendous_probe++;
+       }
 
-static int opendous_khz(int khz, int *jtag_speed)
-{
-       *jtag_speed = khz;
-       /* TODO: convert this into delay value for opendous */
+       if (!opendous_probe) {
+               LOG_ERROR("No matching cable found for %s", opendous_type);
+               return ERROR_JTAG_INIT_FAILED;
+       }
 
-       return ERROR_OK;
-}
 
-static int opendous_init(void)
-{
-       int check_cnt;
+       usb_in_buffer = malloc(opendous_probe->BUFFERSIZE);
+       usb_out_buffer = malloc(opendous_probe->BUFFERSIZE);
+
+       pending_scan_results_buffer = (struct pending_scan_result *)
+                       malloc(MAX_PENDING_SCAN_RESULTS * sizeof(struct pending_scan_result));
 
        opendous_jtag_handle = opendous_usb_open();
 
@@ -336,6 +382,27 @@ static int opendous_init(void)
 static int opendous_quit(void)
 {
        opendous_usb_close(opendous_jtag_handle);
+
+       if (usb_out_buffer) {
+               free(usb_out_buffer);
+               usb_out_buffer = NULL;
+       }
+
+       if (usb_in_buffer) {
+               free(usb_in_buffer);
+               usb_in_buffer = NULL;
+       }
+
+       if (pending_scan_results_buffer) {
+               free(pending_scan_results_buffer);
+               pending_scan_results_buffer = NULL;
+       }
+
+       if (opendous_type) {
+               free(opendous_type);
+               opendous_type = NULL;
+       }
+
        return ERROR_OK;
 }
 
@@ -422,7 +489,9 @@ void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_s
        /* Move to appropriate scan state */
        opendous_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
 
-       opendous_state_move();
+       if (tap_get_state() != tap_get_end_state())
+               opendous_state_move();
+
        opendous_end_state(saved_end_state);
 
        /* Scan */
@@ -465,7 +534,8 @@ void opendous_simple_command(uint8_t command, uint8_t _data)
 
        DEBUG_JTAG_IO("0x%02x 0x%02x", command, _data);
 
-       usb_out_buffer[0] = (uint16_t) 2;
+       usb_out_buffer[0] = 2;
+       usb_out_buffer[1] = 0;
        usb_out_buffer[2] = command;
        usb_out_buffer[3] = _data;
 
@@ -491,16 +561,6 @@ static int tap_length;
 static uint8_t tms_buffer[OPENDOUS_TAP_BUFFER_SIZE];
 static uint8_t tdo_buffer[OPENDOUS_TAP_BUFFER_SIZE];
 
-struct pending_scan_result {
-       int first;      /* First bit position in tdo_buffer to read */
-       int length; /* Number of bits to read */
-       struct scan_command *command; /* Corresponding scan command */
-       uint8_t *buffer;
-};
-
-static int pending_scan_results_length;
-static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
-
 static int last_tms;
 
 void opendous_tap_init(void)
@@ -512,8 +572,9 @@ void opendous_tap_init(void)
 void opendous_tap_ensure_space(int scans, int bits)
 {
        int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length;
+       int available_bits = OPENDOUS_TAP_BUFFER_SIZE / 2 - tap_length;
 
-       if (scans > available_scans)
+       if ((scans > available_scans) || (bits > available_bits))
                opendous_tap_execute();
 }
 
@@ -523,6 +584,8 @@ void opendous_tap_append_step(int tms, int tdi)
        unsigned char _tms = tms ? 1 : 0;
        unsigned char _tdi = tdi ? 1 : 0;
 
+       opendous_tap_ensure_space(0, 1);
+
        int tap_index =  tap_length / 4;
        int bits  = (tap_length % 4) * 2;
 
@@ -578,28 +641,28 @@ int opendous_tap_execute(void)
 
                for (j = 0, i = 0; j <  byte_length;) {
 
-                       int recieve;
+                       int receive;
                        int transmit = byte_length - j;
                        if (transmit > OPENDOUS_MAX_TAP_TRANSMIT) {
                                transmit = OPENDOUS_MAX_TAP_TRANSMIT;
-                               recieve = (OPENDOUS_MAX_TAP_TRANSMIT) / 2;
+                               receive = (OPENDOUS_MAX_TAP_TRANSMIT) / 2;
                                usb_out_buffer[2] = JTAG_CMD_TAP_OUTPUT;
                        } else {
                                usb_out_buffer[2] = JTAG_CMD_TAP_OUTPUT | ((tap_length % 4) << 4);
-                               recieve = (transmit + 1) / 2;
+                               receive = (transmit + 1) / 2;
                        }
                        usb_out_buffer[0] = (transmit + 1) & 0xff;
                        usb_out_buffer[1] = ((transmit + 1) >> 8) & 0xff;
 
                        memmove(usb_out_buffer + 3, tms_buffer + j, transmit);
-                       result = opendous_usb_message(opendous_jtag_handle, 3 + transmit, recieve);
-                       if (result != recieve) {
-                               LOG_ERROR("opendous_tap_execute, wrong result %d, expected %d", result, recieve);
+                       result = opendous_usb_message(opendous_jtag_handle, 3 + transmit, receive);
+                       if (result != receive) {
+                               LOG_ERROR("opendous_tap_execute, wrong result %d, expected %d", result, receive);
                                return ERROR_JTAG_QUEUE_FAILED;
                        }
 
-                       memmove(tdo_buffer + i, usb_in_buffer, recieve);
-                       i += recieve;
+                       memmove(tdo_buffer + i, usb_in_buffer, receive);
+                       i += receive;
                        j += transmit;
                }
 
@@ -649,7 +712,7 @@ struct opendous_jtag *opendous_usb_open(void)
        struct opendous_jtag *result;
 
        struct jtag_libusb_device_handle *devh;
-       if (jtag_libusb_open(vids, pids, &devh) != ERROR_OK)
+       if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, &devh) != ERROR_OK)
                return NULL;
 
        jtag_libusb_set_configuration(devh, 0);
@@ -699,8 +762,14 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
 #ifdef _DEBUG_USB_COMMS_
        LOG_DEBUG("%s: USB write begin", opendous_get_time(time_str));
 #endif
-       result = jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT, \
-               (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
+       if (opendous_probe->CONTROL_TRANSFER) {
+               result = jtag_libusb_control_transfer(opendous_jtag->usb_handle,
+                       LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
+                       FUNC_WRITE_DATA, 0, 0, (char *) usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
+       } else {
+               result = jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT, \
+                       (char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
+       }
 #ifdef _DEBUG_USB_COMMS_
        LOG_DEBUG("%s: USB write end: %d bytes", opendous_get_time(time_str), result);
 #endif
@@ -719,8 +788,15 @@ int opendous_usb_read(struct opendous_jtag *opendous_jtag)
 #ifdef _DEBUG_USB_COMMS_
        LOG_DEBUG("%s: USB read begin", opendous_get_time(time_str));
 #endif
-       int result = jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
-               (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
+       int result;
+       if (opendous_probe->CONTROL_TRANSFER) {
+               result = jtag_libusb_control_transfer(opendous_jtag->usb_handle,
+                       LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
+                       FUNC_READ_DATA, 0, 0, (char *) usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
+       } else {
+               result = jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
+                       (char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
+       }
 #ifdef _DEBUG_USB_COMMS_
        LOG_DEBUG("%s: USB read end: %d bytes", opendous_get_time(time_str), result);
 #endif

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)