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 "replacements.h"
37 #if PARPORT_USE_PPDEV == 1
38 #include <linux/parport.h>
39 #include <linux/ppdev.h>
41 #include <sys/ioctl.h>
43 #else /* not PARPORT_USE_PPDEV */
49 #if PARPORT_USE_GIVEIO == 1
59 static u16 amt_jtagaccel_port
;
61 /* interface variables
63 static u8 aw_control_rst
= 0x00;
64 static u8 aw_control_fsm
= 0x10;
65 static u8 aw_control_baudrate
= 0x20;
67 static int rtck_enabled
= 0;
69 #if PARPORT_USE_PPDEV == 1
70 static int device_handle
;
72 static int addr_mode
= IEEE1284_MODE_EPP
| IEEE1284_ADDR
;
73 #define AMT_AW(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); write(device_handle, &val, 1); } while (0)
74 #define AMT_AR(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); read(device_handle, &val, 1); } while (0)
76 static int data_mode
= IEEE1284_MODE_EPP
| IEEE1284_DATA
;
77 #define AMT_DW(val) do { ioctl(device_handle, PPSETMODE, &data_mode); write(device_handle, &val, 1); } while (0)
78 #define AMT_DR(val) do { ioctl(device_handle, PPSETMODE, &data_mode); read(device_handle, &val, 1); } while (0)
82 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
83 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
84 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
85 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
87 #endif // PARPORT_USE_PPDEV
89 static int amt_jtagaccel_execute_queue(void);
90 static int amt_jtagaccel_register_commands(struct command_context_s
*cmd_ctx
);
91 static int amt_jtagaccel_speed(int speed
);
92 static int amt_jtagaccel_init(void);
93 static int amt_jtagaccel_quit(void);
95 static int amt_jtagaccel_handle_parport_port_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
96 static int amt_jtagaccel_handle_rtck_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
98 /* tap_move[i][j]: tap movement command to go from state i to state j
106 static u8 amt_jtagaccel_tap_move
[6][6][2] =
108 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
109 {{0x1f, 0x00}, {0x0f, 0x00}, {0x8a, 0x04}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00}}, /* RESET */
110 {{0x1f, 0x00}, {0x00, 0x00}, {0x85, 0x08}, {0x05, 0x00}, {0x8b, 0x08}, {0x0b, 0x00}}, /* IDLE */
111 {{0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRSHIFT */
112 {{0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRPAUSE */
113 {{0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00}}, /* IRSHIFT */
114 {{0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00}}, /* IRPAUSE */
118 jtag_interface_t amt_jtagaccel_interface
=
120 .name
= "amt_jtagaccel",
122 .execute_queue
= amt_jtagaccel_execute_queue
,
124 .speed
= amt_jtagaccel_speed
,
125 .register_commands
= amt_jtagaccel_register_commands
,
126 .init
= amt_jtagaccel_init
,
127 .quit
= amt_jtagaccel_quit
,
130 static int amt_jtagaccel_register_commands(struct command_context_s
*cmd_ctx
)
132 register_command(cmd_ctx
, NULL
, "parport_port", amt_jtagaccel_handle_parport_port_command
,
133 COMMAND_CONFIG
, NULL
);
134 register_command(cmd_ctx
, NULL
, "rtck", amt_jtagaccel_handle_rtck_command
,
135 COMMAND_CONFIG
, NULL
);
140 static void amt_jtagaccel_reset(int trst
, int srst
)
143 aw_control_rst
|= 0x4;
145 aw_control_rst
&= ~0x4;
148 aw_control_rst
|= 0x1;
150 aw_control_rst
&= ~0x1;
152 AMT_AW(aw_control_rst
);
155 static int amt_jtagaccel_speed(int speed
)
157 aw_control_baudrate
&= 0xf0;
158 aw_control_baudrate
|= speed
& 0x0f;
159 AMT_AW(aw_control_baudrate
);
164 static void amt_jtagaccel_end_state(tap_state_t state
)
166 if (tap_is_state_stable(state
))
167 tap_set_end_state(state
);
170 LOG_ERROR("BUG: %i is not a valid end state", state
);
175 static void amt_wait_scan_busy(void)
181 while (((ar_status
) & 0x80) && (timeout
-- > 0))
184 if (ar_status
& 0x80)
186 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
);
191 static void amt_jtagaccel_state_move(void)
196 tap_state_t cur_state
= tap_get_state();
197 tap_state_t end_state
= tap_get_end_state();
199 tms_scan
[0] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][0];
200 tms_scan
[1] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][1];
202 aw_scan_tms_5
= 0x40 | (tms_scan
[0] & 0x1f);
203 AMT_AW(aw_scan_tms_5
);
204 if (jtag_speed
> 3 || rtck_enabled
)
205 amt_wait_scan_busy();
207 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
)
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
)
229 amt_jtagaccel_end_state(TAP_IDLE
);
230 amt_jtagaccel_state_move();
233 while (num_cycles
- i
>= 5)
235 aw_scan_tms_5
= 0x40;
236 AMT_AW(aw_scan_tms_5
);
240 if (num_cycles
- i
> 0)
242 aw_scan_tms_1to4
= 0x80 | ((num_cycles
- i
- 1) & 0x3) << 4;
243 AMT_AW(aw_scan_tms_1to4
);
246 amt_jtagaccel_end_state(saved_end_state
);
247 if (tap_get_state() != tap_get_end_state())
248 amt_jtagaccel_state_move();
251 static void amt_jtagaccel_scan(int ir_scan
, enum scan_type type
, u8
*buffer
, int scan_size
)
253 int bits_left
= scan_size
;
255 tap_state_t saved_end_state
= tap_get_end_state();
263 amt_jtagaccel_end_state(TAP_IRSHIFT
);
265 amt_jtagaccel_end_state(TAP_DRSHIFT
);
267 amt_jtagaccel_state_move();
268 amt_jtagaccel_end_state(saved_end_state
);
270 /* handle unaligned bits at the beginning */
271 if ((scan_size
- 1) % 8)
273 aw_tdi_option
= 0x30 | (((scan_size
- 1) % 8) - 1);
274 AMT_AW(aw_tdi_option
);
276 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, (scan_size
- 1) % 8) & 0xff;
278 if (jtag_speed
> 3 || rtck_enabled
)
279 amt_wait_scan_busy();
281 if ((type
== SCAN_IN
) || (type
== SCAN_IO
))
284 dr_tdo
= dr_tdo
>> (8 - ((scan_size
- 1) % 8));
285 buf_set_u32(buffer
, bit_count
, (scan_size
- 1) % 8, dr_tdo
);
288 bit_count
+= (scan_size
- 1) % 8;
289 bits_left
-= (scan_size
- 1) % 8;
292 while (bits_left
- 1 >= 8)
294 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, 8) & 0xff;
296 if (jtag_speed
> 3 || rtck_enabled
)
297 amt_wait_scan_busy();
299 if ((type
== SCAN_IN
) || (type
== SCAN_IO
))
302 buf_set_u32(buffer
, bit_count
, 8, dr_tdo
);
309 tms_scan
[0] = amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
310 tms_scan
[1] = amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
311 aw_tms_scan
= 0x40 | (tms_scan
[0] & 0x1f) | (buf_get_u32(buffer
, bit_count
, 1) << 5);
313 if (jtag_speed
> 3 || rtck_enabled
)
314 amt_wait_scan_busy();
316 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)
325 aw_tms_scan
= 0x40 | (tms_scan
[1] & 0x1f);
327 if (jtag_speed
> 3 || rtck_enabled
)
328 amt_wait_scan_busy();
330 tap_set_state(tap_get_end_state());
333 static int amt_jtagaccel_execute_queue(void)
335 jtag_command_t
*cmd
= jtag_command_queue
; /* currently processed command */
341 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
342 * that wasn't handled by a caller-provided error handler
351 #ifdef _DEBUG_JTAG_IO_
352 LOG_DEBUG("end_state: %i", cmd
->cmd
.end_state
->end_state
);
354 if (cmd
->cmd
.end_state
->end_state
!= TAP_INVALID
)
355 amt_jtagaccel_end_state(cmd
->cmd
.end_state
->end_state
);
358 #ifdef _DEBUG_JTAG_IO_
359 LOG_DEBUG("reset trst: %i srst %i", cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
361 if (cmd
->cmd
.reset
->trst
== 1)
363 tap_set_state(TAP_RESET
);
365 amt_jtagaccel_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
368 #ifdef _DEBUG_JTAG_IO_
369 LOG_DEBUG("runtest %i cycles, end in %i", cmd
->cmd
.runtest
->num_cycles
, cmd
->cmd
.runtest
->end_state
);
371 if (cmd
->cmd
.runtest
->end_state
!= TAP_INVALID
)
372 amt_jtagaccel_end_state(cmd
->cmd
.runtest
->end_state
);
373 amt_jtagaccel_runtest(cmd
->cmd
.runtest
->num_cycles
);
376 #ifdef _DEBUG_JTAG_IO_
377 LOG_DEBUG("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
379 if (cmd
->cmd
.statemove
->end_state
!= TAP_INVALID
)
380 amt_jtagaccel_end_state(cmd
->cmd
.statemove
->end_state
);
381 amt_jtagaccel_state_move();
384 #ifdef _DEBUG_JTAG_IO_
385 LOG_DEBUG("scan end in %i", cmd
->cmd
.scan
->end_state
);
387 if (cmd
->cmd
.scan
->end_state
!= TAP_INVALID
)
388 amt_jtagaccel_end_state(cmd
->cmd
.scan
->end_state
);
389 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
390 type
= jtag_scan_type(cmd
->cmd
.scan
);
391 amt_jtagaccel_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
);
392 if (jtag_read_buffer(buffer
, cmd
->cmd
.scan
) != ERROR_OK
)
393 retval
= ERROR_JTAG_QUEUE_FAILED
;
398 #ifdef _DEBUG_JTAG_IO_
399 LOG_DEBUG("sleep %i", cmd
->cmd
.sleep
->us
);
401 jtag_sleep(cmd
->cmd
.sleep
->us
);
404 LOG_ERROR("BUG: unknown JTAG command type encountered");
413 #if PARPORT_USE_GIVEIO == 1
414 int amt_jtagaccel_get_giveio_access(void)
417 OSVERSIONINFO version
;
419 version
.dwOSVersionInfoSize
= sizeof version
;
420 if (!GetVersionEx( &version
)) {
424 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
427 h
= CreateFile( "\\\\.\\giveio", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
428 if (h
== INVALID_HANDLE_VALUE
) {
439 static int amt_jtagaccel_init(void)
441 #if PARPORT_USE_PPDEV == 1
450 #if PARPORT_USE_PPDEV == 1
451 if (device_handle
> 0)
453 LOG_ERROR("device is already opened");
454 return ERROR_JTAG_INIT_FAILED
;
457 snprintf(buffer
, 256, "/dev/parport%d", amt_jtagaccel_port
);
458 device_handle
= open(buffer
, O_RDWR
);
460 if (device_handle
< 0)
462 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
463 return ERROR_JTAG_INIT_FAILED
;
466 i
= ioctl(device_handle
, PPCLAIM
);
469 LOG_ERROR("cannot claim device");
470 return ERROR_JTAG_INIT_FAILED
;
473 i
= IEEE1284_MODE_EPP
;
474 i
= ioctl(device_handle
, PPSETMODE
, & i
);
477 LOG_ERROR(" cannot set compatible mode to device");
478 return ERROR_JTAG_INIT_FAILED
;
482 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
485 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
488 if (amt_jtagaccel_port
== 0)
490 amt_jtagaccel_port
= 0x378;
491 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
494 #if PARPORT_USE_GIVEIO == 1
495 if (amt_jtagaccel_get_giveio_access() != 0) {
496 #else /* PARPORT_USE_GIVEIO */
497 if (ioperm(amt_jtagaccel_port
, 5, 1) != 0) {
498 #endif /* PARPORT_USE_GIVEIO */
499 LOG_ERROR("missing privileges for direct i/o");
500 return ERROR_JTAG_INIT_FAILED
;
503 /* prepare epp port */
505 status_port
= inb(amt_jtagaccel_port
+ 1);
506 outb(status_port
| 0x1, amt_jtagaccel_port
+ 1);
509 outb(0x00, amt_jtagaccel_port
+ 2);
510 outb(0x04, amt_jtagaccel_port
+ 2);
515 /* set RTCK enable bit */
516 aw_control_fsm
|= 0x02;
519 /* enable JTAG port */
520 aw_control_fsm
|= 0x04;
521 AMT_AW(aw_control_fsm
);
523 amt_jtagaccel_speed(jtag_speed
);
525 if (jtag_reset_config
& RESET_TRST_OPEN_DRAIN
)
526 aw_control_rst
&= ~0x8;
528 aw_control_rst
|= 0x8;
530 if (jtag_reset_config
& RESET_SRST_PUSH_PULL
)
531 aw_control_rst
&= ~0x2;
533 aw_control_rst
|= 0x2;
535 amt_jtagaccel_reset(0, 0);
537 /* read status register */
539 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status
);
544 static int amt_jtagaccel_quit(void)
550 static int amt_jtagaccel_handle_parport_port_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
555 /* only if the port wasn't overwritten by cmdline */
556 if (amt_jtagaccel_port
== 0)
557 amt_jtagaccel_port
= strtoul(args
[0], NULL
, 0);
562 static int amt_jtagaccel_handle_rtck_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
566 command_print(cmd_ctx
, "amt_jtagaccel RTCK feature %s", (rtck_enabled
) ? "enabled" : "disabled");
571 if (strcmp(args
[0], "enabled") == 0)
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)