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, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
23 #include <jtag/adapter.h>
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
;
57 static uint8_t aw_control_fsm
= 0x10;
58 static uint8_t aw_control_baudrate
= 0x20;
60 static int rtck_enabled
;
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 assert(__retval >= 0); \
75 __retval = write(device_handle, &val, 1); \
76 assert(__retval >= 0); \
82 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
83 assert(__retval >= 0); \
84 __retval = read(device_handle, &val, 1); \
85 assert(__retval >= 0); \
88 static const int data_mode
= IEEE1284_MODE_EPP
| IEEE1284_DATA
;
94 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
95 assert(__retval >= 0); \
96 __retval = write(device_handle, &val, 1); \
97 assert(__retval >= 0); \
103 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
104 assert(__retval >= 0); \
105 __retval = read(device_handle, &val, 1); \
106 assert(__retval >= 0); \
111 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
112 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
113 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
114 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
116 #endif /* PARPORT_USE_PPDEV */
118 /* tap_move[i][j]: tap movement command to go from state i to state j
119 * 0: Test-Logic-Reset
126 static const uint8_t amt_jtagaccel_tap_move
[6][6][2] = {
127 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
128 { {0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00} }, /* RESET */
129 { {0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00} }, /* IDLE */
130 { {0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRSHIFT */
131 { {0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRPAUSE */
132 { {0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00} }, /* IRSHIFT */
133 { {0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00} }, /* IRPAUSE */
136 static void amt_jtagaccel_reset(int trst
, int srst
)
139 aw_control_rst
|= 0x4;
141 aw_control_rst
&= ~0x4;
144 aw_control_rst
|= 0x1;
146 aw_control_rst
&= ~0x1;
148 AMT_AW(aw_control_rst
);
151 static int amt_jtagaccel_speed(int speed
)
153 aw_control_baudrate
&= 0xf0;
154 aw_control_baudrate
|= speed
& 0x0f;
155 AMT_AW(aw_control_baudrate
);
160 static void amt_jtagaccel_end_state(tap_state_t state
)
162 if (tap_is_state_stable(state
))
163 tap_set_end_state(state
);
165 LOG_ERROR("BUG: %i is not a valid end state", state
);
170 static void amt_wait_scan_busy(void)
176 while (((ar_status
) & 0x80) && (timeout
-- > 0))
179 if (ar_status
& 0x80) {
181 "amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x",
182 (rtck_enabled
) ? "enabled" : "disabled",
188 static void amt_jtagaccel_state_move(void)
190 uint8_t aw_scan_tms_5
;
193 tap_state_t cur_state
= tap_get_state();
194 tap_state_t end_state
= tap_get_end_state();
196 tms_scan
[0] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][0];
197 tms_scan
[1] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][1];
199 aw_scan_tms_5
= 0x40 | (tms_scan
[0] & 0x1f);
200 AMT_AW(aw_scan_tms_5
);
202 int retval
= adapter_get_speed(&jtag_speed
);
203 assert(retval
== ERROR_OK
);
204 if (jtag_speed
> 3 || rtck_enabled
)
205 amt_wait_scan_busy();
207 if (tms_scan
[0] & 0x80) {
208 aw_scan_tms_5
= 0x40 | (tms_scan
[1] & 0x1f);
209 AMT_AW(aw_scan_tms_5
);
210 if (jtag_speed
> 3 || rtck_enabled
)
211 amt_wait_scan_busy();
214 tap_set_state(end_state
);
217 static void amt_jtagaccel_runtest(int num_cycles
)
220 uint8_t aw_scan_tms_5
;
221 uint8_t aw_scan_tms_1to4
;
223 tap_state_t saved_end_state
= tap_get_end_state();
225 /* only do a state_move when we're not already in IDLE */
226 if (tap_get_state() != TAP_IDLE
) {
227 amt_jtagaccel_end_state(TAP_IDLE
);
228 amt_jtagaccel_state_move();
231 while (num_cycles
- i
>= 5) {
232 aw_scan_tms_5
= 0x40;
233 AMT_AW(aw_scan_tms_5
);
237 if (num_cycles
- i
> 0) {
238 aw_scan_tms_1to4
= 0x80 | ((num_cycles
- i
- 1) & 0x3) << 4;
239 AMT_AW(aw_scan_tms_1to4
);
242 amt_jtagaccel_end_state(saved_end_state
);
243 if (tap_get_state() != tap_get_end_state())
244 amt_jtagaccel_state_move();
247 static void amt_jtagaccel_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
)
249 int bits_left
= scan_size
;
251 tap_state_t saved_end_state
= tap_get_end_state();
252 uint8_t aw_tdi_option
;
258 int retval
= adapter_get_speed(&jtag_speed_var
);
259 assert(retval
== ERROR_OK
);
262 amt_jtagaccel_end_state(TAP_IRSHIFT
);
264 amt_jtagaccel_end_state(TAP_DRSHIFT
);
266 /* Only move if we're not already there */
267 if (tap_get_state() != tap_get_end_state())
268 amt_jtagaccel_state_move();
270 amt_jtagaccel_end_state(saved_end_state
);
272 /* handle unaligned bits at the beginning */
273 if ((scan_size
- 1) % 8) {
274 aw_tdi_option
= 0x30 | (((scan_size
- 1) % 8) - 1);
275 AMT_AW(aw_tdi_option
);
277 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, (scan_size
- 1) % 8) & 0xff;
279 if (jtag_speed_var
> 3 || rtck_enabled
)
280 amt_wait_scan_busy();
282 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) {
293 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, 8) & 0xff;
295 if (jtag_speed_var
> 3 || rtck_enabled
)
296 amt_wait_scan_busy();
298 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
300 buf_set_u32(buffer
, bit_count
, 8, dr_tdo
);
308 amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
310 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_var
> 3 || rtck_enabled
)
314 amt_wait_scan_busy();
316 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
318 dr_tdo
= dr_tdo
>> 7;
319 buf_set_u32(buffer
, bit_count
, 1, dr_tdo
);
322 if (tms_scan
[0] & 0x80) {
323 aw_tms_scan
= 0x40 | (tms_scan
[1] & 0x1f);
325 if (jtag_speed_var
> 3 || rtck_enabled
)
326 amt_wait_scan_busy();
328 tap_set_state(tap_get_end_state());
331 static int amt_jtagaccel_execute_queue(void)
333 struct jtag_command
*cmd
= jtag_command_queue
; /* currently processed command */
339 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
340 * that wasn't handled by a caller-provided error handler
347 LOG_DEBUG_IO("reset trst: %i srst %i",
348 cmd
->cmd
.reset
->trst
,
349 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 LOG_DEBUG_IO("runtest %i cycles, end in %i",
356 cmd
->cmd
.runtest
->num_cycles
,
357 cmd
->cmd
.runtest
->end_state
);
358 amt_jtagaccel_end_state(cmd
->cmd
.runtest
->end_state
);
359 amt_jtagaccel_runtest(cmd
->cmd
.runtest
->num_cycles
);
362 LOG_DEBUG_IO("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
363 amt_jtagaccel_end_state(cmd
->cmd
.statemove
->end_state
);
364 amt_jtagaccel_state_move();
367 LOG_DEBUG_IO("scan end in %i", cmd
->cmd
.scan
->end_state
);
368 amt_jtagaccel_end_state(cmd
->cmd
.scan
->end_state
);
369 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
370 type
= jtag_scan_type(cmd
->cmd
.scan
);
371 amt_jtagaccel_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
);
372 if (jtag_read_buffer(buffer
, cmd
->cmd
.scan
) != ERROR_OK
)
373 retval
= ERROR_JTAG_QUEUE_FAILED
;
377 LOG_DEBUG_IO("sleep %" PRIu32
, cmd
->cmd
.sleep
->us
);
378 jtag_sleep(cmd
->cmd
.sleep
->us
);
381 LOG_ERROR("BUG: unknown JTAG command type encountered");
390 #if PARPORT_USE_GIVEIO == 1
391 int amt_jtagaccel_get_giveio_access(void)
394 OSVERSIONINFO version
;
396 version
.dwOSVersionInfoSize
= sizeof(version
);
397 if (!GetVersionEx(&version
)) {
401 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
404 h
= CreateFile("\\\\.\\giveio",
409 FILE_ATTRIBUTE_NORMAL
,
411 if (h
== INVALID_HANDLE_VALUE
) {
422 static int amt_jtagaccel_init(void)
424 #if PARPORT_USE_PPDEV == 1
427 uint8_t control_port
;
433 #if PARPORT_USE_PPDEV == 1
434 if (device_handle
> 0) {
435 LOG_ERROR("device is already opened");
436 return ERROR_JTAG_INIT_FAILED
;
439 snprintf(buffer
, 256, "/dev/parport%d", amt_jtagaccel_port
);
440 device_handle
= open(buffer
, O_RDWR
);
442 if (device_handle
< 0) {
444 "cannot open device. check it exists and that user read and write rights are set");
445 return ERROR_JTAG_INIT_FAILED
;
448 i
= ioctl(device_handle
, PPCLAIM
);
450 LOG_ERROR("cannot claim device");
451 return ERROR_JTAG_INIT_FAILED
;
454 i
= IEEE1284_MODE_EPP
;
455 i
= ioctl(device_handle
, PPSETMODE
, &i
);
457 LOG_ERROR(" cannot set compatible mode to device");
458 return ERROR_JTAG_INIT_FAILED
;
462 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
465 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
468 if (amt_jtagaccel_port
== 0) {
469 amt_jtagaccel_port
= 0x378;
470 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
473 #if PARPORT_USE_GIVEIO == 1
474 if (amt_jtagaccel_get_giveio_access() != 0) {
475 #else /* PARPORT_USE_GIVEIO */
476 if (ioperm(amt_jtagaccel_port
, 5, 1) != 0) {
477 #endif /* PARPORT_USE_GIVEIO */
478 LOG_ERROR("missing privileges for direct i/o");
479 return ERROR_JTAG_INIT_FAILED
;
484 status_port
= inb(amt_jtagaccel_port
+ 1);
485 outb(status_port
| 0x1, amt_jtagaccel_port
+ 1);
488 outb(0x00, amt_jtagaccel_port
+ 2);
489 outb(0x04, amt_jtagaccel_port
+ 2);
493 /* set RTCK enable bit */
494 aw_control_fsm
|= 0x02;
497 /* enable JTAG port */
498 aw_control_fsm
|= 0x04;
499 AMT_AW(aw_control_fsm
);
501 enum reset_types jtag_reset_config
= jtag_get_reset_config();
502 if (jtag_reset_config
& RESET_TRST_OPEN_DRAIN
)
503 aw_control_rst
&= ~0x8;
505 aw_control_rst
|= 0x8;
507 if (jtag_reset_config
& RESET_SRST_PUSH_PULL
)
508 aw_control_rst
&= ~0x2;
510 aw_control_rst
|= 0x2;
512 amt_jtagaccel_reset(0, 0);
514 /* read status register */
516 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status
);
521 static int amt_jtagaccel_quit(void)
527 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command
)
530 /* only if the port wasn't overwritten by cmdline */
531 if (amt_jtagaccel_port
== 0) {
533 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
534 amt_jtagaccel_port
= port
;
536 LOG_ERROR("The parport port was already configured!");
541 command_print(CMD
, "parport port = %u", amt_jtagaccel_port
);
546 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command
)
550 "amt_jtagaccel RTCK feature %s",
551 (rtck_enabled
) ? "enabled" : "disabled");
554 if (strcmp(CMD_ARGV
[0], "enabled") == 0)
563 static const struct command_registration amtjtagaccel_command_handlers
[] = {
565 .name
= "parport_port",
566 .handler
= &amt_jtagaccel_handle_parport_port_command
,
567 .mode
= COMMAND_CONFIG
,
568 .help
= "configure or display the parallel port to use",
569 .usage
= "[port_num]",
573 * @todo Remove this "rtck" command; just use the standard
574 * mechanism to enable/disable adaptive clocking. First
575 * implement the standard mechanism and deprecate "rtck";
576 * after a year or so, it'll be safe to remove this.
579 .handler
= &amt_jtagaccel_handle_rtck_command
,
580 .mode
= COMMAND_CONFIG
,
581 .help
= "configure or display RTCK support",
582 .usage
= "[enable|disable]",
584 COMMAND_REGISTRATION_DONE
587 static struct jtag_interface amt_jtagaccel_interface
= {
588 .execute_queue
= amt_jtagaccel_execute_queue
,
591 struct adapter_driver amt_jtagaccel_adapter_driver
= {
592 .name
= "amt_jtagaccel",
593 .transports
= jtag_only
,
594 .commands
= amtjtagaccel_command_handlers
,
596 .init
= amt_jtagaccel_init
,
597 .quit
= amt_jtagaccel_quit
,
598 .speed
= amt_jtagaccel_speed
,
600 .jtag_ops
= &amt_jtagaccel_interface
,
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)