- endianess fixes everywhere but in the flash code. flashing might still be broken...
[openocd.git] / src / jtag / ft2232.c
1 /***************************************************************************
2 * Copyright (C) 2004, 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #if IS_CYGWIN == 1
25 #include "windows.h"
26 #undef ERROR
27 #endif
28
29 #include "replacements.h"
30
31 /* project specific includes */
32 #include "log.h"
33 #include "types.h"
34 #include "jtag.h"
35 #include "configuration.h"
36 #include "time_support.h"
37
38 /* system includes */
39 #include <string.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42
43 /* FT2232 access library includes */
44 #if BUILD_FT2232_FTD2XX == 1
45 #include <ftd2xx.h>
46 #elif BUILD_FT2232_LIBFTDI == 1
47 #include <ftdi.h>
48 #endif
49
50 #include <sys/time.h>
51 #include <time.h>
52
53 /* enable this to debug io latency
54 */
55 #if 0
56 #define _DEBUG_USB_IO_
57 #endif
58
59 /* enable this to debug communication
60 */
61 #if 0
62 #define _DEBUG_USB_COMMS_
63 #endif
64
65 int ft2232_execute_queue(void);
66
67 int ft2232_speed(int speed);
68 int ft2232_register_commands(struct command_context_s *cmd_ctx);
69 int ft2232_init(void);
70 int ft2232_quit(void);
71
72 int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
73 int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
74 int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
75
76 char *ft2232_device_desc = NULL;
77 char *ft2232_layout = NULL;
78 u16 ft2232_vid = 0x0403;
79 u16 ft2232_pid = 0x6010;
80
81 typedef struct ft2232_layout_s
82 {
83 char* name;
84 int(*init)(void);
85 void(*reset)(int trst, int srst);
86 void(*blink)(void);
87 } ft2232_layout_t;
88
89 /* init procedures for supported layouts */
90 int usbjtag_init(void);
91 int jtagkey_init(void);
92 int olimex_jtag_init(void);
93
94 /* reset procedures for supported layouts */
95 void usbjtag_reset(int trst, int srst);
96 void jtagkey_reset(int trst, int srst);
97 void olimex_jtag_reset(int trst, int srst);
98
99 /* blink procedures for layouts that support a blinking led */
100 void olimex_jtag_blink(void);
101
102 ft2232_layout_t ft2232_layouts[] =
103 {
104 {"usbjtag", usbjtag_init, usbjtag_reset, NULL},
105 {"jtagkey", jtagkey_init, jtagkey_reset, NULL},
106 {"jtagkey_prototype_v1", jtagkey_init, jtagkey_reset, NULL},
107 {"signalyzer", usbjtag_init, usbjtag_reset, NULL},
108 {"olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink},
109 {NULL, NULL, NULL},
110 };
111
112 static u8 nTRST, nTRSTnOE, nSRST, nSRSTnOE;
113
114 static ft2232_layout_t *layout;
115 static u8 low_output = 0x0;
116 static u8 low_direction = 0x0;
117 static u8 high_output = 0x0;
118 static u8 high_direction = 0x0;
119
120 #if BUILD_FT2232_FTD2XX == 1
121 static FT_HANDLE ftdih = NULL;
122 #elif BUILD_FT2232_LIBFTDI == 1
123 static struct ftdi_context ftdic;
124 #endif
125
126 static u8 *ft2232_buffer = NULL;
127 static int ft2232_buffer_size = 0;
128 static int ft2232_read_pointer = 0;
129 static int ft2232_expect_read = 0;
130 #define FT2232_BUFFER_SIZE 131072
131 #define BUFFER_ADD ft2232_buffer[ft2232_buffer_size++]
132 #define BUFFER_READ ft2232_buffer[ft2232_read_pointer++]
133
134 jtag_interface_t ft2232_interface =
135 {
136
137 .name = "ft2232",
138
139 .execute_queue = ft2232_execute_queue,
140
141 .support_pathmove = 1,
142
143 .speed = ft2232_speed,
144 .register_commands = ft2232_register_commands,
145 .init = ft2232_init,
146 .quit = ft2232_quit,
147 };
148
149 int ft2232_write(u8 *buf, int size, u32* bytes_written)
150 {
151 #if BUILD_FT2232_FTD2XX == 1
152 FT_STATUS status;
153 DWORD dw_bytes_written;
154 if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK)
155 {
156 *bytes_written = dw_bytes_written;
157 ERROR("FT_Write returned: %i", status);
158 return ERROR_JTAG_DEVICE_ERROR;
159 }
160 else
161 {
162 *bytes_written = dw_bytes_written;
163 return ERROR_OK;
164 }
165 #elif BUILD_FT2232_LIBFTDI == 1
166 int retval;
167 if ((retval = ftdi_write_data(&ftdic, buf, size)) < 0)
168 {
169 *bytes_written = 0;
170 ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
171 return ERROR_JTAG_DEVICE_ERROR;
172 }
173 else
174 {
175 *bytes_written = retval;
176 return ERROR_OK;
177 }
178 #endif
179 }
180
181 int ft2232_read(u8* buf, int size, u32* bytes_read)
182 {
183 #if BUILD_FT2232_FTD2XX == 1
184 DWORD dw_bytes_read;
185 FT_STATUS status;
186 if ((status = FT_Read(ftdih, buf, size, &dw_bytes_read)) != FT_OK)
187 {
188 *bytes_read = dw_bytes_read;
189 ERROR("FT_Read returned: %i", status);
190 return ERROR_JTAG_DEVICE_ERROR;
191 }
192 *bytes_read = dw_bytes_read;
193 return ERROR_OK;
194
195 #elif BUILD_FT2232_LIBFTDI == 1
196 int retval;
197 int timeout = 100;
198 *bytes_read = 0;
199
200 while ((*bytes_read < size) && timeout--)
201 {
202 if ((retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read)) < 0)
203 {
204 *bytes_read = 0;
205 ERROR("ftdi_read_data: %s", ftdi_get_error_string(&ftdic));
206 return ERROR_JTAG_DEVICE_ERROR;
207 }
208 *bytes_read += retval;
209 }
210 return ERROR_OK;
211 #endif
212 }
213
214 int ft2232_speed(int speed)
215 {
216 u8 buf[3];
217 int retval;
218 u32 bytes_written;
219
220 buf[0] = 0x86; /* command "set divisor" */
221 buf[1] = speed & 0xff; /* valueL (0=6MHz, 1=3MHz, 2=1.5MHz, ...*/
222 buf[2] = (speed >> 8) & 0xff; /* valueH */
223
224 DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
225 if (((retval = ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
226 {
227 ERROR("couldn't set FT2232 TCK speed");
228 return retval;
229 }
230
231 return ERROR_OK;
232 }
233
234 int ft2232_register_commands(struct command_context_s *cmd_ctx)
235 {
236 register_command(cmd_ctx, NULL, "ft2232_device_desc", ft2232_handle_device_desc_command,
237 COMMAND_CONFIG, NULL);
238 register_command(cmd_ctx, NULL, "ft2232_layout", ft2232_handle_layout_command,
239 COMMAND_CONFIG, NULL);
240 register_command(cmd_ctx, NULL, "ft2232_vid_pid", ft2232_handle_vid_pid_command,
241 COMMAND_CONFIG, NULL);
242 return ERROR_OK;
243 }
244
245 void ft2232_end_state(state)
246 {
247 if (tap_move_map[state] != -1)
248 end_state = state;
249 else
250 {
251 ERROR("BUG: %i is not a valid end state", state);
252 exit(-1);
253 }
254 }
255
256 void ft2232_read_scan(enum scan_type type, u8* buffer, int scan_size)
257 {
258 int num_bytes = ((scan_size + 7) / 8);
259 int bits_left = scan_size;
260 int cur_byte = 0;
261
262 while(num_bytes-- > 1)
263 {
264 buffer[cur_byte] = BUFFER_READ;
265 cur_byte++;
266 bits_left -= 8;
267 }
268
269 buffer[cur_byte] = 0x0;
270
271 if (bits_left > 1)
272 {
273 buffer[cur_byte] = BUFFER_READ >> 1;
274 }
275
276 buffer[cur_byte] = (buffer[cur_byte] | ((BUFFER_READ & 0x02) << 6)) >> (8 - bits_left);
277
278 }
279
280 void ft2232_debug_dump_buffer(void)
281 {
282 int i;
283 char line[256];
284 char *line_p = line;
285
286 for (i = 0; i < ft2232_buffer_size; i++)
287 {
288 line_p += snprintf(line_p, 256 - (line_p - line), "%2.2x ", ft2232_buffer[i]);
289 if (i % 16 == 15)
290 {
291 DEBUG("%s", line);
292 line_p = line;
293 }
294 }
295
296 if (line_p != line)
297 DEBUG("%s", line);
298 }
299
300 int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last)
301 {
302 jtag_command_t *cmd;
303 u8 *buffer;
304 int scan_size;
305 enum scan_type type;
306 int retval;
307 u32 bytes_written;
308 u32 bytes_read;
309
310 #ifdef _DEBUG_USB_IO_
311 struct timeval start, inter, inter2, end;
312 struct timeval d_inter, d_inter2, d_end;
313 #endif
314
315 #ifdef _DEBUG_USB_COMMS_
316 DEBUG("write buffer (size %i):", ft2232_buffer_size);
317 ft2232_debug_dump_buffer();
318 #endif
319
320 #ifdef _DEBUG_USB_IO_
321 gettimeofday(&start, NULL);
322 #endif
323
324 if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
325 {
326 ERROR("couldn't write MPSSE commands to FT2232");
327 exit(-1);
328 }
329
330 #ifdef _DEBUG_USB_IO_
331 gettimeofday(&inter, NULL);
332 #endif
333
334 if (ft2232_expect_read)
335 {
336 int timeout = 100;
337 ft2232_buffer_size = 0;
338
339 #ifdef _DEBUG_USB_IO_
340 gettimeofday(&inter2, NULL);
341 #endif
342
343 if ((retval = ft2232_read(ft2232_buffer, ft2232_expect_read, &bytes_read)) != ERROR_OK)
344 {
345 ERROR("couldn't read from FT2232");
346 exit(-1);
347 }
348
349 #ifdef _DEBUG_USB_IO_
350 gettimeofday(&end, NULL);
351
352 timeval_subtract(&d_inter, &inter, &start);
353 timeval_subtract(&d_inter2, &inter2, &start);
354 timeval_subtract(&d_end, &end, &start);
355
356 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);
357 #endif
358
359
360 ft2232_buffer_size = bytes_read;
361
362 if (ft2232_expect_read != ft2232_buffer_size)
363 {
364 ERROR("ft2232_expect_read (%i) != ft2232_buffer_size (%i) (%i retries)", ft2232_expect_read, ft2232_buffer_size, 100 - timeout);
365 ft2232_debug_dump_buffer();
366
367 exit(-1);
368 }
369
370 #ifdef _DEBUG_USB_COMMS_
371 DEBUG("read buffer (%i retries): %i bytes", 100 - timeout, ft2232_buffer_size);
372 ft2232_debug_dump_buffer();
373 #endif
374 }
375
376 ft2232_expect_read = 0;
377 ft2232_read_pointer = 0;
378
379 cmd = first;
380 while (cmd != last)
381 {
382 switch (cmd->type)
383 {
384 case JTAG_SCAN:
385 type = jtag_scan_type(cmd->cmd.scan);
386 if (type != SCAN_OUT)
387 {
388 scan_size = jtag_scan_size(cmd->cmd.scan);
389 buffer = calloc(CEIL(scan_size, 8), 1);
390 ft2232_read_scan(type, buffer, scan_size);
391 jtag_read_buffer(buffer, cmd->cmd.scan);
392 free(buffer);
393 }
394 break;
395 default:
396 break;
397 }
398 cmd = cmd->next;
399 }
400
401 ft2232_buffer_size = 0;
402
403 return ERROR_OK;
404 }
405
406 void ft2232_add_pathmove(pathmove_command_t *cmd)
407 {
408 int num_states = cmd->num_states;
409 u8 tms_byte;
410 int state_count;
411
412 state_count = 0;
413 while (num_states)
414 {
415 tms_byte = 0x0;
416 int bit_count = 0;
417
418 /* command "Clock Data to TMS/CS Pin (no Read)" */
419 BUFFER_ADD = 0x4b;
420 /* number of states remaining */
421 BUFFER_ADD = (num_states % 7) - 1;
422
423 while (num_states % 7)
424 {
425 if (tap_transitions[cur_state].low == cmd->path[state_count])
426 buf_set_u32(&tms_byte, bit_count++, 1, 0x0);
427 else if (tap_transitions[cur_state].high == cmd->path[state_count])
428 buf_set_u32(&tms_byte, bit_count++, 1, 0x1);
429 else
430 {
431 ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);
432 exit(-1);
433 }
434
435 cur_state = cmd->path[state_count];
436 state_count++;
437 num_states--;
438 }
439
440 BUFFER_ADD = tms_byte;
441 }
442
443 end_state = cur_state;
444 }
445
446 void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
447 {
448 int num_bytes = (scan_size + 7) / 8;
449 int bits_left = scan_size;
450 int cur_byte = 0;
451 int last_bit;
452
453 if ((!ir_scan && (cur_state != TAP_SD)) || (ir_scan && (cur_state != TAP_SI)))
454 {
455 /* command "Clock Data to TMS/CS Pin (no Read)" */
456 BUFFER_ADD = 0x4b;
457 /* scan 7 bit */
458 BUFFER_ADD = 0x6;
459 /* TMS data bits */
460 if (ir_scan)
461 {
462 BUFFER_ADD = TAP_MOVE(cur_state, TAP_SI);
463 cur_state = TAP_SI;
464 }
465 else
466 {
467 BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD);
468 cur_state = TAP_SD;
469 }
470 //DEBUG("added TMS scan (no read)");
471 }
472
473 /* add command for complete bytes */
474 if (num_bytes > 1)
475 {
476 if (type == SCAN_IO)
477 {
478 /* Clock Data Bytes In and Out LSB First */
479 BUFFER_ADD = 0x39;
480 //DEBUG("added TDI bytes (io %i)", num_bytes);
481 }
482 else if (type == SCAN_OUT)
483 {
484 /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
485 BUFFER_ADD = 0x19;
486 //DEBUG("added TDI bytes (o)");
487 }
488 else if (type == SCAN_IN)
489 {
490 /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
491 BUFFER_ADD = 0x28;
492 //DEBUG("added TDI bytes (i %i)", num_bytes);
493 }
494 BUFFER_ADD = (num_bytes-2) & 0xff;
495 BUFFER_ADD = ((num_bytes-2) >> 8) & 0xff;
496 }
497 if (type != SCAN_IN)
498 {
499 /* add complete bytes */
500 while(num_bytes-- > 1)
501 {
502 BUFFER_ADD = buffer[cur_byte];
503 cur_byte++;
504 bits_left -= 8;
505 }
506 }
507 if (type == SCAN_IN)
508 {
509 bits_left -= 8 * (num_bytes - 1);
510 }
511
512 /* the most signifcant bit is scanned during TAP movement */
513 if (type != SCAN_IN)
514 last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;
515 else
516 last_bit = 0;
517
518 /* process remaining bits but the last one */
519 if (bits_left > 1)
520 {
521 if (type == SCAN_IO)
522 {
523 /* Clock Data Bits In and Out LSB First */
524 BUFFER_ADD = 0x3b;
525 //DEBUG("added TDI bits (io) %i", bits_left - 1);
526 }
527 else if (type == SCAN_OUT)
528 {
529 /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
530 BUFFER_ADD = 0x1b;
531 //DEBUG("added TDI bits (o)");
532 }
533 else if (type == SCAN_IN)
534 {
535 /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
536 BUFFER_ADD = 0x2a;
537 //DEBUG("added TDI bits (i %i)", bits_left - 1);
538 }
539 BUFFER_ADD = bits_left - 2;
540 if (type != SCAN_IN)
541 BUFFER_ADD = buffer[cur_byte];
542 }
543
544 /* move from Shift-IR/DR to end state */
545 if (type != SCAN_OUT)
546 {
547 /* Clock Data to TMS/CS Pin with Read */
548 BUFFER_ADD = 0x6b;
549 //DEBUG("added TMS scan (read)");
550 }
551 else
552 {
553 /* Clock Data to TMS/CS Pin (no Read) */
554 BUFFER_ADD = 0x4b;
555 //DEBUG("added TMS scan (no read)");
556 }
557 BUFFER_ADD = 0x6;
558 BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);
559 cur_state = end_state;
560
561 }
562
563 int ft2232_predict_scan_out(int scan_size, enum scan_type type)
564 {
565 int predicted_size = 3;
566
567 if (cur_state != TAP_SD)
568 predicted_size += 3;
569
570 if (type == SCAN_IN) /* only from device to host */
571 {
572 /* complete bytes */
573 predicted_size += (CEIL(scan_size, 8) > 1) ? 3 : 0;
574 /* remaining bits - 1 (up to 7) */
575 predicted_size += ((scan_size - 1) % 8) ? 2 : 0;
576 }
577 else /* host to device, or bidirectional */
578 {
579 /* complete bytes */
580 predicted_size += (CEIL(scan_size, 8) > 1) ? (CEIL(scan_size, 8) + 3 - 1) : 0;
581 /* remaining bits -1 (up to 7) */
582 predicted_size += ((scan_size - 1) % 8) ? 3 : 0;
583 }
584
585 return predicted_size;
586 }
587
588 int ft2232_predict_scan_in(int scan_size, enum scan_type type)
589 {
590 int predicted_size = 0;
591
592 if (type != SCAN_OUT)
593 {
594 /* complete bytes */
595 predicted_size += (CEIL(scan_size, 8) > 1) ? (CEIL(scan_size, 8) - 1) : 0;
596 /* remaining bits - 1 */
597 predicted_size += ((scan_size - 1) % 8) ? 1 : 0;
598 /* last bit (from TMS scan) */
599 predicted_size += 1;
600 }
601
602 //DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size);
603
604 return predicted_size;
605 }
606
607 void usbjtag_reset(int trst, int srst)
608 {
609 if (trst == 1)
610 {
611 cur_state = TAP_TLR;
612 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
613 low_direction |= nTRSTnOE; /* switch to output pin (output is low) */
614 else
615 low_output &= ~nTRST; /* switch output low */
616 }
617 else if (trst == 0)
618 {
619 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
620 low_direction &= ~nTRSTnOE; /* switch to input pin (high-Z + internal and external pullup) */
621 else
622 low_output |= nTRST; /* switch output high */
623 }
624
625 if (srst == 1)
626 {
627 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
628 low_output &= ~nSRST; /* switch output low */
629 else
630 low_direction |= nSRSTnOE; /* switch to output pin (output is low) */
631 }
632 else if (srst == 0)
633 {
634 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
635 low_output |= nSRST; /* switch output high */
636 else
637 low_direction &= ~nSRSTnOE; /* switch to input pin (high-Z) */
638 }
639
640 /* command "set data bits low byte" */
641 BUFFER_ADD = 0x80;
642 BUFFER_ADD = low_output;
643 BUFFER_ADD = low_direction;
644
645 }
646
647 void jtagkey_reset(int trst, int srst)
648 {
649 if (trst == 1)
650 {
651 cur_state = TAP_TLR;
652 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
653 high_output &= ~nTRSTnOE;
654 else
655 high_output &= ~nTRST;
656 }
657 else if (trst == 0)
658 {
659 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
660 high_output |= nTRSTnOE;
661 else
662 high_output |= nTRST;
663 }
664
665 if (srst == 1)
666 {
667 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
668 high_output &= ~nSRST;
669 else
670 high_output &= ~nSRSTnOE;
671 }
672 else if (srst == 0)
673 {
674 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
675 high_output |= nSRST;
676 else
677 high_output |= nSRSTnOE;
678 }
679
680 /* command "set data bits high byte" */
681 BUFFER_ADD = 0x82;
682 BUFFER_ADD = high_output;
683 BUFFER_ADD = high_direction;
684 DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
685 }
686
687 void olimex_jtag_reset(int trst, int srst)
688 {
689 if (trst == 1)
690 {
691 cur_state = TAP_TLR;
692 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
693 high_output &= ~nTRSTnOE;
694 else
695 high_output &= ~nTRST;
696 }
697 else if (trst == 0)
698 {
699 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
700 high_output |= nTRSTnOE;
701 else
702 high_output |= nTRST;
703 }
704
705 if (srst == 1)
706 {
707 high_output |= nSRST;
708 }
709 else if (srst == 0)
710 {
711 high_output &= ~nSRST;
712 }
713
714 /* command "set data bits high byte" */
715 BUFFER_ADD = 0x82;
716 BUFFER_ADD = high_output;
717 BUFFER_ADD = high_direction;
718 DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
719 }
720
721 int ft2232_execute_queue()
722 {
723 jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
724 jtag_command_t *first_unsent = cmd; /* next command that has to be sent */
725 u8 *buffer;
726 int scan_size; /* size of IR or DR scan */
727 enum scan_type type;
728 int i;
729 int predicted_size = 0;
730 int require_send = 0;
731
732 ft2232_buffer_size = 0;
733 ft2232_expect_read = 0;
734
735 /* blink, if the current layout has that feature */
736 if (layout->blink)
737 layout->blink();
738
739 while (cmd)
740 {
741 switch(cmd->type)
742 {
743 case JTAG_END_STATE:
744 if (cmd->cmd.end_state->end_state != -1)
745 ft2232_end_state(cmd->cmd.end_state->end_state);
746 break;
747 case JTAG_RESET:
748 /* only send the maximum buffer size that FT2232C can handle */
749 predicted_size = 3;
750 if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
751 {
752 ft2232_send_and_recv(first_unsent, cmd);
753 require_send = 0;
754 first_unsent = cmd;
755 }
756
757 layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
758 require_send = 1;
759
760 #ifdef _DEBUG_JTAG_IO_
761 DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
762 #endif
763 break;
764 case JTAG_RUNTEST:
765 /* only send the maximum buffer size that FT2232C can handle */
766 predicted_size = 0;
767 if (cur_state != TAP_RTI)
768 predicted_size += 3;
769 predicted_size += 3 * CEIL(cmd->cmd.runtest->num_cycles, 7);
770 if ((cmd->cmd.runtest->end_state != -1) && (cmd->cmd.runtest->end_state != TAP_RTI))
771 predicted_size += 3;
772 if ((cmd->cmd.runtest->end_state == -1) && (end_state != TAP_RTI))
773 predicted_size += 3;
774 if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
775 {
776 ft2232_send_and_recv(first_unsent, cmd);
777 require_send = 0;
778 first_unsent = cmd;
779 }
780 if (cur_state != TAP_RTI)
781 {
782 /* command "Clock Data to TMS/CS Pin (no Read)" */
783 BUFFER_ADD = 0x4b;
784 /* scan 7 bit */
785 BUFFER_ADD = 0x6;
786 /* TMS data bits */
787 BUFFER_ADD = TAP_MOVE(cur_state, TAP_RTI);
788 cur_state = TAP_RTI;
789 require_send = 1;
790 }
791 i = cmd->cmd.runtest->num_cycles;
792 while (i > 0)
793 {
794 /* command "Clock Data to TMS/CS Pin (no Read)" */
795 BUFFER_ADD = 0x4b;
796 /* scan 7 bit */
797 BUFFER_ADD = (i > 7) ? 6 : (i - 1);
798 /* TMS data bits */
799 BUFFER_ADD = 0x0;
800 cur_state = TAP_RTI;
801 i -= (i > 7) ? 7 : i;
802 //DEBUG("added TMS scan (no read)");
803 }
804 if (cmd->cmd.runtest->end_state != -1)
805 ft2232_end_state(cmd->cmd.runtest->end_state);
806 if (cur_state != end_state)
807 {
808 /* command "Clock Data to TMS/CS Pin (no Read)" */
809 BUFFER_ADD = 0x4b;
810 /* scan 7 bit */
811 BUFFER_ADD = 0x6;
812 /* TMS data bits */
813 BUFFER_ADD = TAP_MOVE(cur_state, end_state);
814 cur_state = end_state;
815 //DEBUG("added TMS scan (no read)");
816 }
817 require_send = 1;
818 #ifdef _DEBUG_JTAG_IO_
819 DEBUG("runtest: %i, end in %i", cmd->cmd.runtest->num_cycles, end_state);
820 #endif
821 break;
822 case JTAG_STATEMOVE:
823 /* only send the maximum buffer size that FT2232C can handle */
824 predicted_size = 3;
825 if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
826 {
827 ft2232_send_and_recv(first_unsent, cmd);
828 require_send = 0;
829 first_unsent = cmd;
830 }
831 if (cmd->cmd.statemove->end_state != -1)
832 ft2232_end_state(cmd->cmd.statemove->end_state);
833 /* command "Clock Data to TMS/CS Pin (no Read)" */
834 BUFFER_ADD = 0x4b;
835 /* scan 7 bit */
836 BUFFER_ADD = 0x6;
837 /* TMS data bits */
838 BUFFER_ADD = TAP_MOVE(cur_state, end_state);
839 //DEBUG("added TMS scan (no read)");
840 cur_state = end_state;
841 require_send = 1;
842 #ifdef _DEBUG_JTAG_IO_
843 DEBUG("statemove: %i", end_state);
844 #endif
845 break;
846 case JTAG_PATHMOVE:
847 /* only send the maximum buffer size that FT2232C can handle */
848 predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7);
849 if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
850 {
851 ft2232_send_and_recv(first_unsent, cmd);
852 require_send = 0;
853 first_unsent = cmd;
854 }
855 ft2232_add_pathmove(cmd->cmd.pathmove);
856 require_send = 1;
857 #ifdef _DEBUG_JTAG_IO_
858 DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
859 #endif
860 break;
861 case JTAG_SCAN:
862 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
863 type = jtag_scan_type(cmd->cmd.scan);
864 predicted_size = ft2232_predict_scan_out(scan_size, type);
865 if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
866 {
867 DEBUG("ftd2xx buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd);
868 ft2232_send_and_recv(first_unsent, cmd);
869 require_send = 0;
870 first_unsent = cmd;
871 }
872 ft2232_expect_read += ft2232_predict_scan_in(scan_size, type);
873 //DEBUG("new read size: %i", ft2232_expect_read);
874 if (cmd->cmd.scan->end_state != -1)
875 ft2232_end_state(cmd->cmd.scan->end_state);
876 ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
877 require_send = 1;
878 if (buffer)
879 free(buffer);
880 #ifdef _DEBUG_JTAG_IO_
881 DEBUG("%s scan, %i bit, end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, end_state);
882 #endif
883 break;
884 case JTAG_SLEEP:
885 ft2232_send_and_recv(first_unsent, cmd);
886 first_unsent = cmd->next;
887 jtag_sleep(cmd->cmd.sleep->us);
888 #ifdef _DEBUG_JTAG_IO_
889 DEBUG("sleep %i usec", cmd->cmd.sleep->us);
890 #endif
891 break;
892 default:
893 ERROR("BUG: unknown JTAG command type encountered");
894 exit(-1);
895 }
896 cmd = cmd->next;
897 }
898
899 if (require_send > 0)
900 ft2232_send_and_recv(first_unsent, cmd);
901
902 return ERROR_OK;
903 }
904
905 int ft2232_init(void)
906 {
907 u8 latency_timer;
908 u8 buf[1];
909 int retval;
910 u32 bytes_written;
911
912 #if BUILD_FT2232_FTD2XX == 1
913 FT_STATUS status;
914 #endif
915
916 ft2232_layout_t *cur_layout = ft2232_layouts;
917
918 if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0))
919 {
920 ft2232_layout = "usbjtag";
921 WARNING("No ft2232 layout specified, using default 'usbjtag'");
922 }
923
924 while (cur_layout->name)
925 {
926 if (strcmp(cur_layout->name, ft2232_layout) == 0)
927 {
928 layout = cur_layout;
929 break;
930 }
931 cur_layout++;
932 }
933
934 if (!layout)
935 {
936 ERROR("No matching layout found for %s", ft2232_layout);
937 return ERROR_JTAG_INIT_FAILED;
938 }
939
940 #if BUILD_FT2232_FTD2XX == 1
941 DEBUG("'ft2232' interface using FTD2XX with '%s' layout", ft2232_layout);
942 #elif BUILD_FT2232_LIBFTDI == 1
943 DEBUG("'ft2232' interface using libftdi with '%s' layout", ft2232_layout);
944 #endif
945
946 #if BUILD_FT2232_FTD2XX == 1
947 /* Open by device description */
948 if (ft2232_device_desc == NULL)
949 {
950 WARNING("no ftd2xx device description specified, using default 'Dual RS232'");
951 ft2232_device_desc = "Dual RS232";
952 }
953
954 #if IS_WIN32 == 0
955 /* Add non-standard Vid/Pid to the linux driver */
956 if ((status = FT_SetVIDPID(ft2232_vid, ft2232_pid)) != FT_OK)
957 {
958 WARNING("couldn't add %4.4x:%4.4x", ft2232_vid, ft2232_pid);
959 }
960 #endif
961
962 if ((status = FT_OpenEx(ft2232_device_desc, FT_OPEN_BY_DESCRIPTION, &ftdih)) != FT_OK)
963 {
964 DWORD num_devices;
965
966 ERROR("unable to open ftdi device: %i", status);
967 status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
968 if (status == FT_OK)
969 {
970 char **desc_array = malloc(sizeof(char*) * (num_devices + 1));
971 int i;
972
973 for (i = 0; i < num_devices; i++)
974 desc_array[i] = malloc(64);
975 desc_array[num_devices] = NULL;
976
977 status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
978
979 if (status == FT_OK)
980 {
981 ERROR("ListDevices: %d\n", num_devices);
982 for (i = 0; i < num_devices; i++)
983 ERROR("%i: %s", i, desc_array[i]);
984 }
985
986 for (i = 0; i < num_devices; i++)
987 free(desc_array[i]);
988 free(desc_array);
989 }
990 else
991 {
992 printf("ListDevices: NONE\n");
993 }
994 return ERROR_JTAG_INIT_FAILED;
995 }
996
997 if ((status = FT_SetLatencyTimer(ftdih, 2)) != FT_OK)
998 {
999 ERROR("unable to set latency timer: %i", status);
1000 return ERROR_JTAG_INIT_FAILED;
1001 }
1002
1003 if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK)
1004 {
1005 ERROR("unable to get latency timer: %i", status);
1006 return ERROR_JTAG_INIT_FAILED;
1007 }
1008 else
1009 {
1010 DEBUG("current latency timer: %i", latency_timer);
1011 }
1012
1013 if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK)
1014 {
1015 ERROR("unable to set timeouts: %i", status);
1016 return ERROR_JTAG_INIT_FAILED;
1017 }
1018
1019 if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK)
1020 {
1021 ERROR("unable to enable bit i/o mode: %i", status);
1022 return ERROR_JTAG_INIT_FAILED;
1023 }
1024 #elif BUILD_FT2232_LIBFTDI == 1
1025 if (ftdi_init(&ftdic) < 0)
1026 return ERROR_JTAG_INIT_FAILED;
1027
1028 /* context, vendor id, product id */
1029 if (ftdi_usb_open(&ftdic, ft2232_vid, ft2232_pid) < 0)
1030 {
1031 ERROR("unable to open ftdi device: %s", ftdic.error_str);
1032 return ERROR_JTAG_INIT_FAILED;
1033 }
1034
1035 if (ftdi_usb_reset(&ftdic) < 0)
1036 {
1037 ERROR("unable to reset ftdi device");
1038 return ERROR_JTAG_INIT_FAILED;
1039 }
1040
1041 if (ftdi_set_latency_timer(&ftdic, 2) < 0)
1042 {
1043 ERROR("unable to set latency timer");
1044 return ERROR_JTAG_INIT_FAILED;
1045 }
1046
1047 if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0)
1048 {
1049 ERROR("unable to get latency timer");
1050 return ERROR_JTAG_INIT_FAILED;
1051 }
1052 else
1053 {
1054 DEBUG("current latency timer: %i", latency_timer);
1055 }
1056
1057 ftdic.bitbang_mode = 0; /* Reset controller */
1058 ftdi_enable_bitbang(&ftdic, 0x0b); /* ctx, JTAG I/O mask */
1059
1060 ftdic.bitbang_mode = 2; /* MPSSE mode */
1061 ftdi_enable_bitbang(&ftdic, 0x0b); /* ctx, JTAG I/O mask */
1062 #endif
1063
1064 ft2232_buffer_size = 0;
1065 ft2232_buffer = malloc(FT2232_BUFFER_SIZE);
1066
1067 if (layout->init() != ERROR_OK)
1068 return ERROR_JTAG_INIT_FAILED;
1069
1070 ft2232_speed(jtag_speed);
1071
1072 buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */
1073 if (((retval = ft2232_write(buf, 1, &bytes_written)) != ERROR_OK) || (bytes_written != 1))
1074 {
1075 ERROR("couldn't write to FT2232 to disable loopback");
1076 return ERROR_JTAG_INIT_FAILED;
1077 }
1078
1079 #if BUILD_FT2232_FTD2XX == 1
1080 if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
1081 {
1082 ERROR("error purging ftd2xx device: %i", status);
1083 return ERROR_JTAG_INIT_FAILED;
1084 }
1085 #elif BUILD_FT2232_LIBFTDI == 1
1086 if (ftdi_usb_purge_buffers(&ftdic) < 0)
1087 {
1088 ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
1089 return ERROR_JTAG_INIT_FAILED;
1090 }
1091 #endif
1092
1093 return ERROR_OK;
1094 }
1095
1096 int usbjtag_init(void)
1097 {
1098 u8 buf[3];
1099 u32 bytes_written;
1100
1101 low_output = 0x08;
1102 low_direction = 0x0b;
1103
1104 if (strcmp(ft2232_layout, "usbjtag") == 0)
1105 {
1106 nTRST = 0x10;
1107 nTRSTnOE = 0x10;
1108 nSRST = 0x40;
1109 nSRSTnOE = 0x40;
1110 }
1111 else if (strcmp(ft2232_layout, "signalyzer") == 0)
1112 {
1113 nTRST = 0x10;
1114 nTRSTnOE = 0x10;
1115 nSRST = 0x20;
1116 nSRSTnOE = 0x20;
1117 }
1118 else
1119 {
1120 ERROR("BUG: usbjtag_init called for unknown layout '%s'", ft2232_layout);
1121 return ERROR_JTAG_INIT_FAILED;
1122 }
1123
1124 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
1125 {
1126 low_direction &= ~nTRSTnOE; /* nTRST input */
1127 low_output &= ~nTRST; /* nTRST = 0 */
1128 }
1129 else
1130 {
1131 low_direction |= nTRSTnOE; /* nTRST output */
1132 low_output |= nTRST; /* nTRST = 1 */
1133 }
1134
1135 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
1136 {
1137 low_direction |= nSRSTnOE; /* nSRST output */
1138 low_output |= nSRST; /* nSRST = 1 */
1139 }
1140 else
1141 {
1142 low_direction &= ~nSRSTnOE; /* nSRST input */
1143 low_output &= ~nSRST; /* nSRST = 0 */
1144 }
1145
1146 /* initialize low byte for jtag */
1147 buf[0] = 0x80; /* command "set data bits low byte" */
1148 buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, xRST high) */
1149 buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in */
1150 DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
1151
1152 if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
1153 {
1154 ERROR("couldn't initialize FT2232 with 'USBJTAG' layout");
1155 return ERROR_JTAG_INIT_FAILED;
1156 }
1157
1158 return ERROR_OK;
1159 }
1160
1161 int jtagkey_init(void)
1162 {
1163 u8 buf[3];
1164 u32 bytes_written;
1165
1166 low_output = 0x08;
1167 low_direction = 0x1b;
1168
1169 /* initialize low byte for jtag */
1170 buf[0] = 0x80; /* command "set data bits low byte" */
1171 buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
1172 buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */
1173 DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
1174
1175 if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
1176 {
1177 ERROR("couldn't initialize FT2232 with 'JTAGkey' layout");
1178 return ERROR_JTAG_INIT_FAILED;
1179 }
1180
1181 if (strcmp(layout->name, "jtagkey") == 0)
1182 {
1183 nTRST = 0x01;
1184 nTRSTnOE = 0x4;
1185 nSRST = 0x02;
1186 nSRSTnOE = 0x08;
1187 }
1188 else if (strcmp(layout->name, "jtagkey_prototype_v1") == 0)
1189 {
1190 nTRST = 0x02;
1191 nTRSTnOE = 0x1;
1192 nSRST = 0x08;
1193 nSRSTnOE = 0x04;
1194 }
1195 else
1196 {
1197 ERROR("BUG: jtagkey_init called for non jtagkey layout");
1198 exit(-1);
1199 }
1200
1201 high_output = 0x0;
1202 high_direction = 0x0f;
1203
1204 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
1205 {
1206 high_output |= nTRSTnOE;
1207 high_output &= ~nTRST;
1208 }
1209 else
1210 {
1211 high_output &= ~nTRSTnOE;
1212 high_output |= nTRST;
1213 }
1214
1215 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
1216 {
1217 high_output &= ~nSRSTnOE;
1218 high_output |= nSRST;
1219 }
1220 else
1221 {
1222 high_output |= nSRSTnOE;
1223 high_output &= ~nSRST;
1224 }
1225
1226 /* initialize high port */
1227 buf[0] = 0x82; /* command "set data bits high byte" */
1228 buf[1] = high_output; /* value */
1229 buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */
1230 DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
1231
1232 if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
1233 {
1234 ERROR("couldn't initialize FT2232 with 'JTAGkey' layout");
1235 return ERROR_JTAG_INIT_FAILED;
1236 }
1237
1238 return ERROR_OK;
1239 }
1240
1241 int olimex_jtag_init(void)
1242 {
1243 u8 buf[3];
1244 u32 bytes_written;
1245
1246 low_output = 0x08;
1247 low_direction = 0x1b;
1248
1249 /* initialize low byte for jtag */
1250 buf[0] = 0x80; /* command "set data bits low byte" */
1251 buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
1252 buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */
1253 DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
1254
1255 if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
1256 {
1257 ERROR("couldn't initialize FT2232 with 'JTAGkey' layout");
1258 return ERROR_JTAG_INIT_FAILED;
1259 }
1260
1261 nTRST = 0x01;
1262 nTRSTnOE = 0x4;
1263 nSRST = 0x02;
1264 nSRSTnOE = 0x00; /* no output enable for nSRST */
1265
1266 high_output = 0x0;
1267 high_direction = 0x0f;
1268
1269 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
1270 {
1271 high_output |= nTRSTnOE;
1272 high_output &= ~nTRST;
1273 }
1274 else
1275 {
1276 high_output &= ~nTRSTnOE;
1277 high_output |= nTRST;
1278 }
1279
1280 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
1281 {
1282 ERROR("can't set nSRST to push-pull on the Olimex ARM-USB-OCD");
1283 }
1284 else
1285 {
1286 high_output &= ~nSRST;
1287 }
1288
1289 /* turn red LED on */
1290 high_output |= 0x08;
1291
1292 /* initialize high port */
1293 buf[0] = 0x82; /* command "set data bits high byte" */
1294 buf[1] = high_output; /* value */
1295 buf[2] = high_direction; /* all outputs (xRST and xRSTnOE) */
1296 DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
1297
1298 if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
1299 {
1300 ERROR("couldn't initialize FT2232 with 'JTAGkey' layout");
1301 return ERROR_JTAG_INIT_FAILED;
1302 }
1303
1304 return ERROR_OK;
1305 }
1306
1307 void olimex_jtag_blink(void)
1308 {
1309 /* Olimex ARM-USB-OCD has a LED connected to ACBUS3
1310 * ACBUS3 is bit 3 of the GPIOH port
1311 */
1312 if (high_output & 0x08)
1313 {
1314 /* set port pin high */
1315 high_output &= 0x07;
1316 }
1317 else
1318 {
1319 /* set port pin low */
1320 high_output |= 0x08;
1321 }
1322
1323 BUFFER_ADD = 0x82;
1324 BUFFER_ADD = high_output;
1325 BUFFER_ADD = high_direction;
1326 }
1327
1328 int ft2232_quit(void)
1329 {
1330 #if BUILD_FT2232_FTD2XX == 1
1331 FT_STATUS status;
1332
1333 status = FT_Close(ftdih);
1334 #elif BUILD_FT2232_LIBFTDI == 1
1335 ftdi_disable_bitbang(&ftdic);
1336
1337 ftdi_usb_close(&ftdic);
1338
1339 ftdi_deinit(&ftdic);
1340 #endif
1341
1342 free(ft2232_buffer);
1343
1344 return ERROR_OK;
1345 }
1346
1347 int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1348 {
1349 if (argc == 1)
1350 {
1351 ft2232_device_desc = strdup(args[0]);
1352 }
1353 else
1354 {
1355 ERROR("expected exactly one argument to ft2232_device_desc <description>");
1356 }
1357
1358 return ERROR_OK;
1359 }
1360
1361 int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1362 {
1363 if (argc == 0)
1364 return ERROR_OK;
1365
1366 ft2232_layout = malloc(strlen(args[0]) + 1);
1367 strcpy(ft2232_layout, args[0]);
1368
1369 return ERROR_OK;
1370 }
1371
1372 int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1373 {
1374 if (argc >= 2)
1375 {
1376 ft2232_vid = strtol(args[0], NULL, 0);
1377 ft2232_pid = strtol(args[1], NULL, 0);
1378 }
1379 else
1380 {
1381 WARNING("incomplete ft2232_vid_pid configuration directive");
1382 }
1383
1384 return ERROR_OK;
1385 }

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)