1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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. *
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. *
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 ***************************************************************************/
25 #include <jtag/interface.h>
27 #if PARPORT_USE_PPDEV == 1
28 #include <linux/parport.h>
29 #include <linux/ppdev.h>
30 #include <sys/ioctl.h>
31 #else /* not PARPORT_USE_PPDEV */
37 #if PARPORT_USE_GIVEIO == 1
45 * Support the Amontec Chameleon POD with JTAG Accelerator support.
46 * This is a parallel port JTAG adapter with a CPLD between the
47 * parallel port and the JTAG connection. VHDL code running in the
48 * CPLD significantly accelerates JTAG operations compared to the
49 * bitbanging "Wiggler" style of most parallel port adapters.
53 static uint16_t amt_jtagaccel_port
;
55 /* interface variables
57 static uint8_t aw_control_rst
;
58 static uint8_t aw_control_fsm
= 0x10;
59 static uint8_t aw_control_baudrate
= 0x20;
61 static int rtck_enabled
;
63 #if PARPORT_USE_PPDEV == 1
64 static int device_handle
;
66 static const int addr_mode
= IEEE1284_MODE_EPP
| IEEE1284_ADDR
;
68 /* FIXME do something sane when these ioctl/read/write calls fail. */
74 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
75 assert(__retval >= 0); \
76 __retval = write(device_handle, &val, 1); \
77 assert(__retval >= 0); \
83 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
84 assert(__retval >= 0); \
85 __retval = read(device_handle, &val, 1); \
86 assert(__retval >= 0); \
89 static const int data_mode
= IEEE1284_MODE_EPP
| IEEE1284_DATA
;
95 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
96 assert(__retval >= 0); \
97 __retval = write(device_handle, &val, 1); \
98 assert(__retval >= 0); \
100 #define AMT_DR(val) \
104 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
105 assert(__retval >= 0); \
106 __retval = read(device_handle, &val, 1); \
107 assert(__retval >= 0); \
112 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
113 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
114 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
115 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
117 #endif /* PARPORT_USE_PPDEV */
119 /* tap_move[i][j]: tap movement command to go from state i to state j
120 * 0: Test-Logic-Reset
127 static uint8_t amt_jtagaccel_tap_move
[6][6][2] = {
128 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
129 { {0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00} }, /* RESET */
130 { {0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00} }, /* IDLE */
131 { {0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRSHIFT */
132 { {0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRPAUSE */
133 { {0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00} }, /* IRSHIFT */
134 { {0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00} }, /* IRPAUSE */
137 static void amt_jtagaccel_reset(int trst
, int srst
)
140 aw_control_rst
|= 0x4;
142 aw_control_rst
&= ~0x4;
145 aw_control_rst
|= 0x1;
147 aw_control_rst
&= ~0x1;
149 AMT_AW(aw_control_rst
);
152 static int amt_jtagaccel_speed(int speed
)
154 aw_control_baudrate
&= 0xf0;
155 aw_control_baudrate
|= speed
& 0x0f;
156 AMT_AW(aw_control_baudrate
);
161 static void amt_jtagaccel_end_state(tap_state_t state
)
163 if (tap_is_state_stable(state
))
164 tap_set_end_state(state
);
166 LOG_ERROR("BUG: %i is not a valid end state", state
);
171 static void amt_wait_scan_busy(void)
177 while (((ar_status
) & 0x80) && (timeout
-- > 0))
180 if (ar_status
& 0x80) {
182 "amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x",
183 (rtck_enabled
) ? "enabled" : "disabled",
189 static void amt_jtagaccel_state_move(void)
191 uint8_t aw_scan_tms_5
;
194 tap_state_t cur_state
= tap_get_state();
195 tap_state_t end_state
= tap_get_end_state();
197 tms_scan
[0] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][0];
198 tms_scan
[1] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][1];
200 aw_scan_tms_5
= 0x40 | (tms_scan
[0] & 0x1f);
201 AMT_AW(aw_scan_tms_5
);
203 int retval
= jtag_get_speed(&jtag_speed
);
204 assert(retval
== ERROR_OK
);
205 if (jtag_speed
> 3 || rtck_enabled
)
206 amt_wait_scan_busy();
208 if (tms_scan
[0] & 0x80) {
209 aw_scan_tms_5
= 0x40 | (tms_scan
[1] & 0x1f);
210 AMT_AW(aw_scan_tms_5
);
211 if (jtag_speed
> 3 || rtck_enabled
)
212 amt_wait_scan_busy();
215 tap_set_state(end_state
);
218 static void amt_jtagaccel_runtest(int num_cycles
)
221 uint8_t aw_scan_tms_5
;
222 uint8_t aw_scan_tms_1to4
;
224 tap_state_t saved_end_state
= tap_get_end_state();
226 /* only do a state_move when we're not already in IDLE */
227 if (tap_get_state() != TAP_IDLE
) {
228 amt_jtagaccel_end_state(TAP_IDLE
);
229 amt_jtagaccel_state_move();
232 while (num_cycles
- i
>= 5) {
233 aw_scan_tms_5
= 0x40;
234 AMT_AW(aw_scan_tms_5
);
238 if (num_cycles
- i
> 0) {
239 aw_scan_tms_1to4
= 0x80 | ((num_cycles
- i
- 1) & 0x3) << 4;
240 AMT_AW(aw_scan_tms_1to4
);
243 amt_jtagaccel_end_state(saved_end_state
);
244 if (tap_get_state() != tap_get_end_state())
245 amt_jtagaccel_state_move();
248 static void amt_jtagaccel_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
)
250 int bits_left
= scan_size
;
252 tap_state_t saved_end_state
= tap_get_end_state();
253 uint8_t aw_tdi_option
;
259 int retval
= jtag_get_speed(&jtag_speed_var
);
260 assert(retval
== ERROR_OK
);
263 amt_jtagaccel_end_state(TAP_IRSHIFT
);
265 amt_jtagaccel_end_state(TAP_DRSHIFT
);
267 /* Only move if we're not already there */
268 if (tap_get_state() != tap_get_end_state())
269 amt_jtagaccel_state_move();
271 amt_jtagaccel_end_state(saved_end_state
);
273 /* handle unaligned bits at the beginning */
274 if ((scan_size
- 1) % 8) {
275 aw_tdi_option
= 0x30 | (((scan_size
- 1) % 8) - 1);
276 AMT_AW(aw_tdi_option
);
278 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, (scan_size
- 1) % 8) & 0xff;
280 if (jtag_speed_var
> 3 || rtck_enabled
)
281 amt_wait_scan_busy();
283 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
285 dr_tdo
= dr_tdo
>> (8 - ((scan_size
- 1) % 8));
286 buf_set_u32(buffer
, bit_count
, (scan_size
- 1) % 8, dr_tdo
);
289 bit_count
+= (scan_size
- 1) % 8;
290 bits_left
-= (scan_size
- 1) % 8;
293 while (bits_left
- 1 >= 8) {
294 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, 8) & 0xff;
296 if (jtag_speed_var
> 3 || rtck_enabled
)
297 amt_wait_scan_busy();
299 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
301 buf_set_u32(buffer
, bit_count
, 8, dr_tdo
);
309 amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
311 amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
312 aw_tms_scan
= 0x40 | (tms_scan
[0] & 0x1f) | (buf_get_u32(buffer
, bit_count
, 1) << 5);
314 if (jtag_speed_var
> 3 || rtck_enabled
)
315 amt_wait_scan_busy();
317 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
319 dr_tdo
= dr_tdo
>> 7;
320 buf_set_u32(buffer
, bit_count
, 1, dr_tdo
);
323 if (tms_scan
[0] & 0x80) {
324 aw_tms_scan
= 0x40 | (tms_scan
[1] & 0x1f);
326 if (jtag_speed_var
> 3 || rtck_enabled
)
327 amt_wait_scan_busy();
329 tap_set_state(tap_get_end_state());
332 static int amt_jtagaccel_execute_queue(void)
334 struct jtag_command
*cmd
= jtag_command_queue
; /* currently processed command */
340 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
341 * that wasn't handled by a caller-provided error handler
348 #ifdef _DEBUG_JTAG_IO_
349 LOG_DEBUG("reset trst: %i srst %i",
350 cmd
->cmd
.reset
->trst
,
351 cmd
->cmd
.reset
->srst
);
353 if (cmd
->cmd
.reset
->trst
== 1)
354 tap_set_state(TAP_RESET
);
355 amt_jtagaccel_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
358 #ifdef _DEBUG_JTAG_IO_
359 LOG_DEBUG("runtest %i cycles, end in %i",
360 cmd
->cmd
.runtest
->num_cycles
,
361 cmd
->cmd
.runtest
->end_state
);
363 amt_jtagaccel_end_state(cmd
->cmd
.runtest
->end_state
);
364 amt_jtagaccel_runtest(cmd
->cmd
.runtest
->num_cycles
);
367 #ifdef _DEBUG_JTAG_IO_
368 LOG_DEBUG("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
370 amt_jtagaccel_end_state(cmd
->cmd
.statemove
->end_state
);
371 amt_jtagaccel_state_move();
374 #ifdef _DEBUG_JTAG_IO_
375 LOG_DEBUG("scan end in %i", cmd
->cmd
.scan
->end_state
);
377 amt_jtagaccel_end_state(cmd
->cmd
.scan
->end_state
);
378 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
379 type
= jtag_scan_type(cmd
->cmd
.scan
);
380 amt_jtagaccel_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
);
381 if (jtag_read_buffer(buffer
, cmd
->cmd
.scan
) != ERROR_OK
)
382 retval
= ERROR_JTAG_QUEUE_FAILED
;
387 #ifdef _DEBUG_JTAG_IO_
388 LOG_DEBUG("sleep %" PRIi32
, cmd
->cmd
.sleep
->us
);
390 jtag_sleep(cmd
->cmd
.sleep
->us
);
393 LOG_ERROR("BUG: unknown JTAG command type encountered");
402 #if PARPORT_USE_GIVEIO == 1
403 int amt_jtagaccel_get_giveio_access(void)
406 OSVERSIONINFO version
;
408 version
.dwOSVersionInfoSize
= sizeof version
;
409 if (!GetVersionEx(&version
)) {
413 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
416 h
= CreateFile("\\\\.\\giveio",
421 FILE_ATTRIBUTE_NORMAL
,
423 if (h
== INVALID_HANDLE_VALUE
) {
434 static int amt_jtagaccel_init(void)
436 #if PARPORT_USE_PPDEV == 1
439 uint8_t control_port
;
445 #if PARPORT_USE_PPDEV == 1
446 if (device_handle
> 0) {
447 LOG_ERROR("device is already opened");
448 return ERROR_JTAG_INIT_FAILED
;
451 snprintf(buffer
, 256, "/dev/parport%d", amt_jtagaccel_port
);
452 device_handle
= open(buffer
, O_RDWR
);
454 if (device_handle
< 0) {
456 "cannot open device. check it exists and that user read and write rights are set");
457 return ERROR_JTAG_INIT_FAILED
;
460 i
= ioctl(device_handle
, PPCLAIM
);
462 LOG_ERROR("cannot claim device");
463 return ERROR_JTAG_INIT_FAILED
;
466 i
= IEEE1284_MODE_EPP
;
467 i
= ioctl(device_handle
, PPSETMODE
, &i
);
469 LOG_ERROR(" cannot set compatible mode to device");
470 return ERROR_JTAG_INIT_FAILED
;
474 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
477 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
480 if (amt_jtagaccel_port
== 0) {
481 amt_jtagaccel_port
= 0x378;
482 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
485 #if PARPORT_USE_GIVEIO == 1
486 if (amt_jtagaccel_get_giveio_access() != 0) {
487 #else /* PARPORT_USE_GIVEIO */
488 if (ioperm(amt_jtagaccel_port
, 5, 1) != 0) {
489 #endif /* PARPORT_USE_GIVEIO */
490 LOG_ERROR("missing privileges for direct i/o");
491 return ERROR_JTAG_INIT_FAILED
;
496 status_port
= inb(amt_jtagaccel_port
+ 1);
497 outb(status_port
| 0x1, amt_jtagaccel_port
+ 1);
500 outb(0x00, amt_jtagaccel_port
+ 2);
501 outb(0x04, amt_jtagaccel_port
+ 2);
505 /* set RTCK enable bit */
506 aw_control_fsm
|= 0x02;
509 /* enable JTAG port */
510 aw_control_fsm
|= 0x04;
511 AMT_AW(aw_control_fsm
);
513 enum reset_types jtag_reset_config
= jtag_get_reset_config();
514 if (jtag_reset_config
& RESET_TRST_OPEN_DRAIN
)
515 aw_control_rst
&= ~0x8;
517 aw_control_rst
|= 0x8;
519 if (jtag_reset_config
& RESET_SRST_PUSH_PULL
)
520 aw_control_rst
&= ~0x2;
522 aw_control_rst
|= 0x2;
524 amt_jtagaccel_reset(0, 0);
526 /* read status register */
528 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status
);
533 static int amt_jtagaccel_quit(void)
539 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command
)
542 /* only if the port wasn't overwritten by cmdline */
543 if (amt_jtagaccel_port
== 0) {
545 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
546 amt_jtagaccel_port
= port
;
548 LOG_ERROR("The parport port was already configured!");
553 command_print(CMD_CTX
, "parport port = %u", amt_jtagaccel_port
);
558 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command
)
561 command_print(CMD_CTX
,
562 "amt_jtagaccel RTCK feature %s",
563 (rtck_enabled
) ? "enabled" : "disabled");
566 if (strcmp(CMD_ARGV
[0], "enabled") == 0)
575 static const struct command_registration amtjtagaccel_command_handlers
[] = {
577 .name
= "parport_port",
578 .handler
= &amt_jtagaccel_handle_parport_port_command
,
579 .mode
= COMMAND_CONFIG
,
580 .help
= "configure or display the parallel port to use",
581 .usage
= "[port_num]",
585 * @todo Remove this "rtck" command; just use the standard
586 * mechanism to enable/disable adaptive clocking. First
587 * implement the standard mechanism and deprecate "rtck";
588 * after a year or so, it'll be safe to remove this.
591 .handler
= &amt_jtagaccel_handle_rtck_command
,
592 .mode
= COMMAND_CONFIG
,
593 .help
= "configure or display RTCK support",
594 .usage
= "[enable|disable]",
596 COMMAND_REGISTRATION_DONE
599 struct jtag_interface amt_jtagaccel_interface
= {
600 .name
= "amt_jtagaccel",
601 .commands
= amtjtagaccel_command_handlers
,
603 .init
= amt_jtagaccel_init
,
604 .quit
= amt_jtagaccel_quit
,
605 .speed
= amt_jtagaccel_speed
,
606 .execute_queue
= amt_jtagaccel_execute_queue
,
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)