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 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) {
272 aw_tdi_option
= 0x30 | (((scan_size
- 1) % 8) - 1);
273 AMT_AW(aw_tdi_option
);
275 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, (scan_size
- 1) % 8) & 0xff;
277 if (jtag_speed_var
> 3 || rtck_enabled
)
278 amt_wait_scan_busy();
280 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
282 dr_tdo
= dr_tdo
>> (8 - ((scan_size
- 1) % 8));
283 buf_set_u32(buffer
, bit_count
, (scan_size
- 1) % 8, dr_tdo
);
286 bit_count
+= (scan_size
- 1) % 8;
287 bits_left
-= (scan_size
- 1) % 8;
290 while (bits_left
- 1 >= 8) {
291 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, 8) & 0xff;
293 if (jtag_speed_var
> 3 || rtck_enabled
)
294 amt_wait_scan_busy();
296 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
298 buf_set_u32(buffer
, bit_count
, 8, dr_tdo
);
306 amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
308 amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
309 aw_tms_scan
= 0x40 | (tms_scan
[0] & 0x1f) | (buf_get_u32(buffer
, bit_count
, 1) << 5);
311 if (jtag_speed_var
> 3 || rtck_enabled
)
312 amt_wait_scan_busy();
314 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
316 dr_tdo
= dr_tdo
>> 7;
317 buf_set_u32(buffer
, bit_count
, 1, dr_tdo
);
320 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
345 #ifdef _DEBUG_JTAG_IO_
346 LOG_DEBUG("reset trst: %i srst %i",
347 cmd
->cmd
.reset
->trst
,
348 cmd
->cmd
.reset
->srst
);
350 if (cmd
->cmd
.reset
->trst
== 1)
351 tap_set_state(TAP_RESET
);
352 amt_jtagaccel_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
355 #ifdef _DEBUG_JTAG_IO_
356 LOG_DEBUG("runtest %i cycles, end in %i",
357 cmd
->cmd
.runtest
->num_cycles
,
358 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",
418 FILE_ATTRIBUTE_NORMAL
,
420 if (h
== INVALID_HANDLE_VALUE
) {
431 static int amt_jtagaccel_init(void)
433 #if PARPORT_USE_PPDEV == 1
436 uint8_t control_port
;
442 #if PARPORT_USE_PPDEV == 1
443 if (device_handle
> 0) {
444 LOG_ERROR("device is already opened");
445 return ERROR_JTAG_INIT_FAILED
;
448 snprintf(buffer
, 256, "/dev/parport%d", amt_jtagaccel_port
);
449 device_handle
= open(buffer
, O_RDWR
);
451 if (device_handle
< 0) {
453 "cannot open device. check it exists and that user read and write rights are set");
454 return ERROR_JTAG_INIT_FAILED
;
457 i
= ioctl(device_handle
, PPCLAIM
);
459 LOG_ERROR("cannot claim device");
460 return ERROR_JTAG_INIT_FAILED
;
463 i
= IEEE1284_MODE_EPP
;
464 i
= ioctl(device_handle
, PPSETMODE
, &i
);
466 LOG_ERROR(" cannot set compatible mode to device");
467 return ERROR_JTAG_INIT_FAILED
;
471 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
474 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
477 if (amt_jtagaccel_port
== 0) {
478 amt_jtagaccel_port
= 0x378;
479 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
482 #if PARPORT_USE_GIVEIO == 1
483 if (amt_jtagaccel_get_giveio_access() != 0) {
484 #else /* PARPORT_USE_GIVEIO */
485 if (ioperm(amt_jtagaccel_port
, 5, 1) != 0) {
486 #endif /* PARPORT_USE_GIVEIO */
487 LOG_ERROR("missing privileges for direct i/o");
488 return ERROR_JTAG_INIT_FAILED
;
493 status_port
= inb(amt_jtagaccel_port
+ 1);
494 outb(status_port
| 0x1, amt_jtagaccel_port
+ 1);
497 outb(0x00, amt_jtagaccel_port
+ 2);
498 outb(0x04, amt_jtagaccel_port
+ 2);
502 /* set RTCK enable bit */
503 aw_control_fsm
|= 0x02;
506 /* enable JTAG port */
507 aw_control_fsm
|= 0x04;
508 AMT_AW(aw_control_fsm
);
510 enum reset_types jtag_reset_config
= jtag_get_reset_config();
511 if (jtag_reset_config
& RESET_TRST_OPEN_DRAIN
)
512 aw_control_rst
&= ~0x8;
514 aw_control_rst
|= 0x8;
516 if (jtag_reset_config
& RESET_SRST_PUSH_PULL
)
517 aw_control_rst
&= ~0x2;
519 aw_control_rst
|= 0x2;
521 amt_jtagaccel_reset(0, 0);
523 /* read status register */
525 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status
);
530 static int amt_jtagaccel_quit(void)
536 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command
)
539 /* only if the port wasn't overwritten by cmdline */
540 if (amt_jtagaccel_port
== 0) {
542 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
543 amt_jtagaccel_port
= port
;
545 LOG_ERROR("The parport port was already configured!");
550 command_print(CMD_CTX
, "parport port = %u", amt_jtagaccel_port
);
555 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command
)
558 command_print(CMD_CTX
,
559 "amt_jtagaccel RTCK feature %s",
560 (rtck_enabled
) ? "enabled" : "disabled");
563 if (strcmp(CMD_ARGV
[0], "enabled") == 0)
572 static const struct command_registration amtjtagaccel_command_handlers
[] = {
574 .name
= "parport_port",
575 .handler
= &amt_jtagaccel_handle_parport_port_command
,
576 .mode
= COMMAND_CONFIG
,
577 .help
= "configure or display the parallel port to use",
578 .usage
= "[port_num]",
582 * @todo Remove this "rtck" command; just use the standard
583 * mechanism to enable/disable adaptive clocking. First
584 * implement the standard mechanism and deprecate "rtck";
585 * after a year or so, it'll be safe to remove this.
588 .handler
= &amt_jtagaccel_handle_rtck_command
,
589 .mode
= COMMAND_CONFIG
,
590 .help
= "configure or display RTCK support",
591 .usage
= "[enable|disable]",
593 COMMAND_REGISTRATION_DONE
596 struct jtag_interface amt_jtagaccel_interface
= {
597 .name
= "amt_jtagaccel",
598 .commands
= amtjtagaccel_command_handlers
,
600 .init
= amt_jtagaccel_init
,
601 .quit
= amt_jtagaccel_quit
,
602 .speed
= amt_jtagaccel_speed
,
603 .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)