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 ***************************************************************************/
24 #include <jtag/interface.h>
25 #include <jtag/commands.h>
28 #if PARPORT_USE_PPDEV == 1
29 #include <linux/parport.h>
30 #include <linux/ppdev.h>
31 #include <sys/ioctl.h>
32 #else /* not PARPORT_USE_PPDEV */
38 #if PARPORT_USE_GIVEIO == 1
45 static uint16_t amt_jtagaccel_port
;
47 /* interface variables
49 static uint8_t aw_control_rst
= 0x00;
50 static uint8_t aw_control_fsm
= 0x10;
51 static uint8_t aw_control_baudrate
= 0x20;
53 static int rtck_enabled
= 0;
55 #if PARPORT_USE_PPDEV == 1
56 static int device_handle
;
58 static const int addr_mode
= IEEE1284_MODE_EPP
| IEEE1284_ADDR
;
60 /* FIXME do something sane when these ioctl/read/write calls fail. */
66 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
67 __retval = write(device_handle, &val, 1); \
73 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
74 __retval = read(device_handle, &val, 1); \
77 static const int data_mode
= IEEE1284_MODE_EPP
| IEEE1284_DATA
;
83 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
84 __retval = write(device_handle, &val, 1); \
90 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
91 __retval = read(device_handle, &val, 1); \
96 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
97 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
98 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
99 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
101 #endif // PARPORT_USE_PPDEV
103 /* tap_move[i][j]: tap movement command to go from state i to state j
104 * 0: Test-Logic-Reset
111 static uint8_t amt_jtagaccel_tap_move
[6][6][2] =
113 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
114 {{0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00}}, /* RESET */
115 {{0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00}}, /* IDLE */
116 {{0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRSHIFT */
117 {{0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRPAUSE */
118 {{0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00}}, /* IRSHIFT */
119 {{0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00}}, /* IRPAUSE */
123 static void amt_jtagaccel_reset(int trst
, int srst
)
126 aw_control_rst
|= 0x4;
128 aw_control_rst
&= ~0x4;
131 aw_control_rst
|= 0x1;
133 aw_control_rst
&= ~0x1;
135 AMT_AW(aw_control_rst
);
138 static int amt_jtagaccel_speed(int speed
)
140 aw_control_baudrate
&= 0xf0;
141 aw_control_baudrate
|= speed
& 0x0f;
142 AMT_AW(aw_control_baudrate
);
147 static void amt_jtagaccel_end_state(tap_state_t state
)
149 if (tap_is_state_stable(state
))
150 tap_set_end_state(state
);
153 LOG_ERROR("BUG: %i is not a valid end state", state
);
158 static void amt_wait_scan_busy(void)
164 while (((ar_status
) & 0x80) && (timeout
-- > 0))
167 if (ar_status
& 0x80)
169 LOG_ERROR("amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x", (rtck_enabled
) ? "enabled" : "disabled", ar_status
);
174 static void amt_jtagaccel_state_move(void)
176 uint8_t aw_scan_tms_5
;
179 tap_state_t cur_state
= tap_get_state();
180 tap_state_t end_state
= tap_get_end_state();
182 tms_scan
[0] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][0];
183 tms_scan
[1] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][1];
185 aw_scan_tms_5
= 0x40 | (tms_scan
[0] & 0x1f);
186 AMT_AW(aw_scan_tms_5
);
187 int jtag_speed
= jtag_get_speed();
188 if (jtag_speed
> 3 || rtck_enabled
)
189 amt_wait_scan_busy();
191 if (tms_scan
[0] & 0x80)
193 aw_scan_tms_5
= 0x40 | (tms_scan
[1] & 0x1f);
194 AMT_AW(aw_scan_tms_5
);
195 if (jtag_speed
> 3 || rtck_enabled
)
196 amt_wait_scan_busy();
199 tap_set_state(end_state
);
202 static void amt_jtagaccel_runtest(int num_cycles
)
205 uint8_t aw_scan_tms_5
;
206 uint8_t aw_scan_tms_1to4
;
208 tap_state_t saved_end_state
= tap_get_end_state();
210 /* only do a state_move when we're not already in IDLE */
211 if (tap_get_state() != TAP_IDLE
)
213 amt_jtagaccel_end_state(TAP_IDLE
);
214 amt_jtagaccel_state_move();
217 while (num_cycles
- i
>= 5)
219 aw_scan_tms_5
= 0x40;
220 AMT_AW(aw_scan_tms_5
);
224 if (num_cycles
- i
> 0)
226 aw_scan_tms_1to4
= 0x80 | ((num_cycles
- i
- 1) & 0x3) << 4;
227 AMT_AW(aw_scan_tms_1to4
);
230 amt_jtagaccel_end_state(saved_end_state
);
231 if (tap_get_state() != tap_get_end_state())
232 amt_jtagaccel_state_move();
235 static void amt_jtagaccel_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
)
237 int bits_left
= scan_size
;
239 tap_state_t saved_end_state
= tap_get_end_state();
240 uint8_t aw_tdi_option
;
245 int jtag_speed
= jtag_get_speed();
248 amt_jtagaccel_end_state(TAP_IRSHIFT
);
250 amt_jtagaccel_end_state(TAP_DRSHIFT
);
252 amt_jtagaccel_state_move();
253 amt_jtagaccel_end_state(saved_end_state
);
255 /* handle unaligned bits at the beginning */
256 if ((scan_size
- 1) % 8)
258 aw_tdi_option
= 0x30 | (((scan_size
- 1) % 8) - 1);
259 AMT_AW(aw_tdi_option
);
261 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, (scan_size
- 1) % 8) & 0xff;
263 if (jtag_speed
> 3 || rtck_enabled
)
264 amt_wait_scan_busy();
266 if ((type
== SCAN_IN
) || (type
== SCAN_IO
))
269 dr_tdo
= dr_tdo
>> (8 - ((scan_size
- 1) % 8));
270 buf_set_u32(buffer
, bit_count
, (scan_size
- 1) % 8, dr_tdo
);
273 bit_count
+= (scan_size
- 1) % 8;
274 bits_left
-= (scan_size
- 1) % 8;
277 while (bits_left
- 1 >= 8)
279 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, 8) & 0xff;
281 if (jtag_speed
> 3 || rtck_enabled
)
282 amt_wait_scan_busy();
284 if ((type
== SCAN_IN
) || (type
== SCAN_IO
))
287 buf_set_u32(buffer
, bit_count
, 8, dr_tdo
);
294 tms_scan
[0] = amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
295 tms_scan
[1] = amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
296 aw_tms_scan
= 0x40 | (tms_scan
[0] & 0x1f) | (buf_get_u32(buffer
, bit_count
, 1) << 5);
298 if (jtag_speed
> 3 || rtck_enabled
)
299 amt_wait_scan_busy();
301 if ((type
== SCAN_IN
) || (type
== SCAN_IO
))
304 dr_tdo
= dr_tdo
>> 7;
305 buf_set_u32(buffer
, bit_count
, 1, dr_tdo
);
308 if (tms_scan
[0] & 0x80)
310 aw_tms_scan
= 0x40 | (tms_scan
[1] & 0x1f);
312 if (jtag_speed
> 3 || rtck_enabled
)
313 amt_wait_scan_busy();
315 tap_set_state(tap_get_end_state());
318 static int amt_jtagaccel_execute_queue(void)
320 struct jtag_command
*cmd
= jtag_command_queue
; /* currently processed command */
326 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
327 * that wasn't handled by a caller-provided error handler
336 #ifdef _DEBUG_JTAG_IO_
337 LOG_DEBUG("reset trst: %i srst %i", cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
339 if (cmd
->cmd
.reset
->trst
== 1)
341 tap_set_state(TAP_RESET
);
343 amt_jtagaccel_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
346 #ifdef _DEBUG_JTAG_IO_
347 LOG_DEBUG("runtest %i cycles, end in %i", cmd
->cmd
.runtest
->num_cycles
, cmd
->cmd
.runtest
->end_state
);
349 amt_jtagaccel_end_state(cmd
->cmd
.runtest
->end_state
);
350 amt_jtagaccel_runtest(cmd
->cmd
.runtest
->num_cycles
);
353 #ifdef _DEBUG_JTAG_IO_
354 LOG_DEBUG("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
356 amt_jtagaccel_end_state(cmd
->cmd
.statemove
->end_state
);
357 amt_jtagaccel_state_move();
360 #ifdef _DEBUG_JTAG_IO_
361 LOG_DEBUG("scan end in %i", cmd
->cmd
.scan
->end_state
);
363 amt_jtagaccel_end_state(cmd
->cmd
.scan
->end_state
);
364 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
365 type
= jtag_scan_type(cmd
->cmd
.scan
);
366 amt_jtagaccel_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
);
367 if (jtag_read_buffer(buffer
, cmd
->cmd
.scan
) != ERROR_OK
)
368 retval
= ERROR_JTAG_QUEUE_FAILED
;
373 #ifdef _DEBUG_JTAG_IO_
374 LOG_DEBUG("sleep %" PRIi32
, cmd
->cmd
.sleep
->us
);
376 jtag_sleep(cmd
->cmd
.sleep
->us
);
379 LOG_ERROR("BUG: unknown JTAG command type encountered");
388 #if PARPORT_USE_GIVEIO == 1
389 int amt_jtagaccel_get_giveio_access(void)
392 OSVERSIONINFO version
;
394 version
.dwOSVersionInfoSize
= sizeof version
;
395 if (!GetVersionEx(&version
)) {
399 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
402 h
= CreateFile("\\\\.\\giveio", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
403 if (h
== INVALID_HANDLE_VALUE
) {
414 static int amt_jtagaccel_init(void)
416 #if PARPORT_USE_PPDEV == 1
419 uint8_t control_port
;
425 #if PARPORT_USE_PPDEV == 1
426 if (device_handle
> 0)
428 LOG_ERROR("device is already opened");
429 return ERROR_JTAG_INIT_FAILED
;
432 snprintf(buffer
, 256, "/dev/parport%d", amt_jtagaccel_port
);
433 device_handle
= open(buffer
, O_RDWR
);
435 if (device_handle
< 0)
437 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
438 return ERROR_JTAG_INIT_FAILED
;
441 i
= ioctl(device_handle
, PPCLAIM
);
444 LOG_ERROR("cannot claim device");
445 return ERROR_JTAG_INIT_FAILED
;
448 i
= IEEE1284_MODE_EPP
;
449 i
= ioctl(device_handle
, PPSETMODE
, & i
);
452 LOG_ERROR(" cannot set compatible mode to device");
453 return ERROR_JTAG_INIT_FAILED
;
457 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
460 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
463 if (amt_jtagaccel_port
== 0)
465 amt_jtagaccel_port
= 0x378;
466 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
469 #if PARPORT_USE_GIVEIO == 1
470 if (amt_jtagaccel_get_giveio_access() != 0) {
471 #else /* PARPORT_USE_GIVEIO */
472 if (ioperm(amt_jtagaccel_port
, 5, 1) != 0) {
473 #endif /* PARPORT_USE_GIVEIO */
474 LOG_ERROR("missing privileges for direct i/o");
475 return ERROR_JTAG_INIT_FAILED
;
478 /* prepare epp port */
480 status_port
= inb(amt_jtagaccel_port
+ 1);
481 outb(status_port
| 0x1, amt_jtagaccel_port
+ 1);
484 outb(0x00, amt_jtagaccel_port
+ 2);
485 outb(0x04, amt_jtagaccel_port
+ 2);
490 /* set RTCK enable bit */
491 aw_control_fsm
|= 0x02;
494 /* enable JTAG port */
495 aw_control_fsm
|= 0x04;
496 AMT_AW(aw_control_fsm
);
498 amt_jtagaccel_speed(jtag_get_speed());
500 enum reset_types jtag_reset_config
= jtag_get_reset_config();
501 if (jtag_reset_config
& RESET_TRST_OPEN_DRAIN
)
502 aw_control_rst
&= ~0x8;
504 aw_control_rst
|= 0x8;
506 if (jtag_reset_config
& RESET_SRST_PUSH_PULL
)
507 aw_control_rst
&= ~0x2;
509 aw_control_rst
|= 0x2;
511 amt_jtagaccel_reset(0, 0);
513 /* read status register */
515 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status
);
520 static int amt_jtagaccel_quit(void)
526 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command
)
530 /* only if the port wasn't overwritten by cmdline */
531 if (amt_jtagaccel_port
== 0)
534 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
535 amt_jtagaccel_port
= port
;
539 LOG_ERROR("The parport port was already configured!");
544 command_print(CMD_CTX
, "parport port = %u", amt_jtagaccel_port
);
549 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command
)
553 command_print(CMD_CTX
, "amt_jtagaccel RTCK feature %s", (rtck_enabled
) ? "enabled" : "disabled");
558 if (strcmp(CMD_ARGV
[0], "enabled") == 0)
571 static const struct command_registration amtjtagaccel_command_handlers
[] = {
573 .name
= "parport_port",
574 .handler
= &amt_jtagaccel_handle_parport_port_command
,
575 .mode
= COMMAND_CONFIG
,
576 .help
= "configure the parallel port to use",
577 .usage
= "<port_num>",
580 .name
= "parport_port",
581 .handler
= &amt_jtagaccel_handle_rtck_command
,
582 .mode
= COMMAND_CONFIG
,
583 .help
= "enable RTCK",
584 .usage
= "<enable|disable>",
586 COMMAND_REGISTRATION_DONE
589 struct jtag_interface amt_jtagaccel_interface
= {
590 .name
= "amt_jtagaccel",
591 .commands
= amtjtagaccel_command_handlers
,
593 .init
= amt_jtagaccel_init
,
594 .quit
= amt_jtagaccel_quit
,
595 .speed
= amt_jtagaccel_speed
,
596 .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)