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>
26 #if PARPORT_USE_PPDEV == 1
27 #include <linux/parport.h>
28 #include <linux/ppdev.h>
29 #include <sys/ioctl.h>
30 #else /* not PARPORT_USE_PPDEV */
36 #if PARPORT_USE_GIVEIO == 1
44 * Support the Amontec Chameleon POD with JTAG Accelerator support.
45 * This is a parallel port JTAG adapter with a CPLD between the
46 * parallel port and the JTAG connection. VHDL code running in the
47 * CPLD significantly accelerates JTAG operations compared to the
48 * bitbanging "Wiggler" style of most parallel port adapters.
52 static uint16_t amt_jtagaccel_port
;
54 /* interface variables
56 static uint8_t aw_control_rst
= 0x00;
57 static uint8_t aw_control_fsm
= 0x10;
58 static uint8_t aw_control_baudrate
= 0x20;
60 static int rtck_enabled
= 0;
62 #if PARPORT_USE_PPDEV == 1
63 static int device_handle
;
65 static const int addr_mode
= IEEE1284_MODE_EPP
| IEEE1284_ADDR
;
67 /* FIXME do something sane when these ioctl/read/write calls fail. */
73 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
74 __retval = write(device_handle, &val, 1); \
80 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
81 __retval = read(device_handle, &val, 1); \
84 static const int data_mode
= IEEE1284_MODE_EPP
| IEEE1284_DATA
;
90 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
91 __retval = write(device_handle, &val, 1); \
97 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
98 __retval = read(device_handle, &val, 1); \
103 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
104 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
105 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
106 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
108 #endif // PARPORT_USE_PPDEV
110 /* tap_move[i][j]: tap movement command to go from state i to state j
111 * 0: Test-Logic-Reset
118 static uint8_t amt_jtagaccel_tap_move
[6][6][2] =
120 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
121 {{0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00}}, /* RESET */
122 {{0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00}}, /* IDLE */
123 {{0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRSHIFT */
124 {{0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRPAUSE */
125 {{0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00}}, /* IRSHIFT */
126 {{0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00}}, /* IRPAUSE */
130 static void amt_jtagaccel_reset(int trst
, int srst
)
133 aw_control_rst
|= 0x4;
135 aw_control_rst
&= ~0x4;
138 aw_control_rst
|= 0x1;
140 aw_control_rst
&= ~0x1;
142 AMT_AW(aw_control_rst
);
145 static int amt_jtagaccel_speed(int speed
)
147 aw_control_baudrate
&= 0xf0;
148 aw_control_baudrate
|= speed
& 0x0f;
149 AMT_AW(aw_control_baudrate
);
154 static void amt_jtagaccel_end_state(tap_state_t state
)
156 if (tap_is_state_stable(state
))
157 tap_set_end_state(state
);
160 LOG_ERROR("BUG: %i is not a valid end state", state
);
165 static void amt_wait_scan_busy(void)
171 while (((ar_status
) & 0x80) && (timeout
-- > 0))
174 if (ar_status
& 0x80)
176 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
);
181 static void amt_jtagaccel_state_move(void)
183 uint8_t aw_scan_tms_5
;
186 tap_state_t cur_state
= tap_get_state();
187 tap_state_t end_state
= tap_get_end_state();
189 tms_scan
[0] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][0];
190 tms_scan
[1] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][1];
192 aw_scan_tms_5
= 0x40 | (tms_scan
[0] & 0x1f);
193 AMT_AW(aw_scan_tms_5
);
195 int retval
= jtag_get_speed(&jtag_speed
);
196 assert(retval
== ERROR_OK
);
197 if (jtag_speed
> 3 || rtck_enabled
)
198 amt_wait_scan_busy();
200 if (tms_scan
[0] & 0x80)
202 aw_scan_tms_5
= 0x40 | (tms_scan
[1] & 0x1f);
203 AMT_AW(aw_scan_tms_5
);
204 if (jtag_speed
> 3 || rtck_enabled
)
205 amt_wait_scan_busy();
208 tap_set_state(end_state
);
211 static void amt_jtagaccel_runtest(int num_cycles
)
214 uint8_t aw_scan_tms_5
;
215 uint8_t aw_scan_tms_1to4
;
217 tap_state_t saved_end_state
= tap_get_end_state();
219 /* only do a state_move when we're not already in IDLE */
220 if (tap_get_state() != TAP_IDLE
)
222 amt_jtagaccel_end_state(TAP_IDLE
);
223 amt_jtagaccel_state_move();
226 while (num_cycles
- i
>= 5)
228 aw_scan_tms_5
= 0x40;
229 AMT_AW(aw_scan_tms_5
);
233 if (num_cycles
- i
> 0)
235 aw_scan_tms_1to4
= 0x80 | ((num_cycles
- i
- 1) & 0x3) << 4;
236 AMT_AW(aw_scan_tms_1to4
);
239 amt_jtagaccel_end_state(saved_end_state
);
240 if (tap_get_state() != tap_get_end_state())
241 amt_jtagaccel_state_move();
244 static void amt_jtagaccel_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
)
246 int bits_left
= scan_size
;
248 tap_state_t saved_end_state
= tap_get_end_state();
249 uint8_t aw_tdi_option
;
255 int retval
= jtag_get_speed(&jtag_speed_var
);
256 assert(retval
== ERROR_OK
);
259 amt_jtagaccel_end_state(TAP_IRSHIFT
);
261 amt_jtagaccel_end_state(TAP_DRSHIFT
);
263 amt_jtagaccel_state_move();
264 amt_jtagaccel_end_state(saved_end_state
);
266 /* handle unaligned bits at the beginning */
267 if ((scan_size
- 1) % 8)
269 aw_tdi_option
= 0x30 | (((scan_size
- 1) % 8) - 1);
270 AMT_AW(aw_tdi_option
);
272 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, (scan_size
- 1) % 8) & 0xff;
274 if (jtag_speed_var
> 3 || rtck_enabled
)
275 amt_wait_scan_busy();
277 if ((type
== SCAN_IN
) || (type
== SCAN_IO
))
280 dr_tdo
= dr_tdo
>> (8 - ((scan_size
- 1) % 8));
281 buf_set_u32(buffer
, bit_count
, (scan_size
- 1) % 8, dr_tdo
);
284 bit_count
+= (scan_size
- 1) % 8;
285 bits_left
-= (scan_size
- 1) % 8;
288 while (bits_left
- 1 >= 8)
290 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, 8) & 0xff;
292 if (jtag_speed_var
> 3 || rtck_enabled
)
293 amt_wait_scan_busy();
295 if ((type
== SCAN_IN
) || (type
== SCAN_IO
))
298 buf_set_u32(buffer
, bit_count
, 8, dr_tdo
);
305 tms_scan
[0] = amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
306 tms_scan
[1] = amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
307 aw_tms_scan
= 0x40 | (tms_scan
[0] & 0x1f) | (buf_get_u32(buffer
, bit_count
, 1) << 5);
309 if (jtag_speed_var
> 3 || rtck_enabled
)
310 amt_wait_scan_busy();
312 if ((type
== SCAN_IN
) || (type
== SCAN_IO
))
315 dr_tdo
= dr_tdo
>> 7;
316 buf_set_u32(buffer
, bit_count
, 1, dr_tdo
);
319 if (tms_scan
[0] & 0x80)
321 aw_tms_scan
= 0x40 | (tms_scan
[1] & 0x1f);
323 if (jtag_speed_var
> 3 || rtck_enabled
)
324 amt_wait_scan_busy();
326 tap_set_state(tap_get_end_state());
329 static int amt_jtagaccel_execute_queue(void)
331 struct jtag_command
*cmd
= jtag_command_queue
; /* currently processed command */
337 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
338 * that wasn't handled by a caller-provided error handler
347 #ifdef _DEBUG_JTAG_IO_
348 LOG_DEBUG("reset trst: %i srst %i", cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
350 if (cmd
->cmd
.reset
->trst
== 1)
352 tap_set_state(TAP_RESET
);
354 amt_jtagaccel_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
357 #ifdef _DEBUG_JTAG_IO_
358 LOG_DEBUG("runtest %i cycles, end in %i", cmd
->cmd
.runtest
->num_cycles
, cmd
->cmd
.runtest
->end_state
);
360 amt_jtagaccel_end_state(cmd
->cmd
.runtest
->end_state
);
361 amt_jtagaccel_runtest(cmd
->cmd
.runtest
->num_cycles
);
364 #ifdef _DEBUG_JTAG_IO_
365 LOG_DEBUG("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
367 amt_jtagaccel_end_state(cmd
->cmd
.statemove
->end_state
);
368 amt_jtagaccel_state_move();
371 #ifdef _DEBUG_JTAG_IO_
372 LOG_DEBUG("scan end in %i", cmd
->cmd
.scan
->end_state
);
374 amt_jtagaccel_end_state(cmd
->cmd
.scan
->end_state
);
375 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
376 type
= jtag_scan_type(cmd
->cmd
.scan
);
377 amt_jtagaccel_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
);
378 if (jtag_read_buffer(buffer
, cmd
->cmd
.scan
) != ERROR_OK
)
379 retval
= ERROR_JTAG_QUEUE_FAILED
;
384 #ifdef _DEBUG_JTAG_IO_
385 LOG_DEBUG("sleep %" PRIi32
, cmd
->cmd
.sleep
->us
);
387 jtag_sleep(cmd
->cmd
.sleep
->us
);
390 LOG_ERROR("BUG: unknown JTAG command type encountered");
399 #if PARPORT_USE_GIVEIO == 1
400 int amt_jtagaccel_get_giveio_access(void)
403 OSVERSIONINFO version
;
405 version
.dwOSVersionInfoSize
= sizeof version
;
406 if (!GetVersionEx(&version
)) {
410 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
413 h
= CreateFile("\\\\.\\giveio", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
414 if (h
== INVALID_HANDLE_VALUE
) {
425 static int amt_jtagaccel_init(void)
427 #if PARPORT_USE_PPDEV == 1
430 uint8_t control_port
;
436 #if PARPORT_USE_PPDEV == 1
437 if (device_handle
> 0)
439 LOG_ERROR("device is already opened");
440 return ERROR_JTAG_INIT_FAILED
;
443 snprintf(buffer
, 256, "/dev/parport%d", amt_jtagaccel_port
);
444 device_handle
= open(buffer
, O_RDWR
);
446 if (device_handle
< 0)
448 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
449 return ERROR_JTAG_INIT_FAILED
;
452 i
= ioctl(device_handle
, PPCLAIM
);
455 LOG_ERROR("cannot claim device");
456 return ERROR_JTAG_INIT_FAILED
;
459 i
= IEEE1284_MODE_EPP
;
460 i
= ioctl(device_handle
, PPSETMODE
, & i
);
463 LOG_ERROR(" cannot set compatible mode to device");
464 return ERROR_JTAG_INIT_FAILED
;
468 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
471 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
474 if (amt_jtagaccel_port
== 0)
476 amt_jtagaccel_port
= 0x378;
477 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
480 #if PARPORT_USE_GIVEIO == 1
481 if (amt_jtagaccel_get_giveio_access() != 0) {
482 #else /* PARPORT_USE_GIVEIO */
483 if (ioperm(amt_jtagaccel_port
, 5, 1) != 0) {
484 #endif /* PARPORT_USE_GIVEIO */
485 LOG_ERROR("missing privileges for direct i/o");
486 return ERROR_JTAG_INIT_FAILED
;
489 /* prepare epp port */
491 status_port
= inb(amt_jtagaccel_port
+ 1);
492 outb(status_port
| 0x1, amt_jtagaccel_port
+ 1);
495 outb(0x00, amt_jtagaccel_port
+ 2);
496 outb(0x04, amt_jtagaccel_port
+ 2);
501 /* set RTCK enable bit */
502 aw_control_fsm
|= 0x02;
505 /* enable JTAG port */
506 aw_control_fsm
|= 0x04;
507 AMT_AW(aw_control_fsm
);
509 enum reset_types jtag_reset_config
= jtag_get_reset_config();
510 if (jtag_reset_config
& RESET_TRST_OPEN_DRAIN
)
511 aw_control_rst
&= ~0x8;
513 aw_control_rst
|= 0x8;
515 if (jtag_reset_config
& RESET_SRST_PUSH_PULL
)
516 aw_control_rst
&= ~0x2;
518 aw_control_rst
|= 0x2;
520 amt_jtagaccel_reset(0, 0);
522 /* read status register */
524 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status
);
529 static int amt_jtagaccel_quit(void)
535 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command
)
539 /* only if the port wasn't overwritten by cmdline */
540 if (amt_jtagaccel_port
== 0)
543 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
544 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
)
562 command_print(CMD_CTX
, "amt_jtagaccel RTCK feature %s", (rtck_enabled
) ? "enabled" : "disabled");
567 if (strcmp(CMD_ARGV
[0], "enabled") == 0)
580 static const struct command_registration amtjtagaccel_command_handlers
[] = {
582 .name
= "parport_port",
583 .handler
= &amt_jtagaccel_handle_parport_port_command
,
584 .mode
= COMMAND_CONFIG
,
585 .help
= "configure or display the parallel port to use",
586 .usage
= "[port_num]",
590 * @todo Remove this "rtck" command; just use the standard
591 * mechanism to enable/disable adaptive clocking. First
592 * implement the standard mechanism and deprecate "rtck";
593 * after a year or so, it'll be safe to remove this.
596 .handler
= &amt_jtagaccel_handle_rtck_command
,
597 .mode
= COMMAND_CONFIG
,
598 .help
= "configure or display RTCK support",
599 .usage
= "[enable|disable]",
601 COMMAND_REGISTRATION_DONE
604 struct jtag_interface amt_jtagaccel_interface
= {
605 .name
= "amt_jtagaccel",
606 .commands
= amtjtagaccel_command_handlers
,
608 .init
= amt_jtagaccel_init
,
609 .quit
= amt_jtagaccel_quit
,
610 .speed
= amt_jtagaccel_speed
,
611 .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)