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/interface.h>
25 #if PARPORT_USE_PPDEV == 1
26 #include <linux/parport.h>
27 #include <linux/ppdev.h>
28 #include <sys/ioctl.h>
29 #else /* not PARPORT_USE_PPDEV */
35 #if PARPORT_USE_GIVEIO == 1
43 * Support the Amontec Chameleon POD with JTAG Accelerator support.
44 * This is a parallel port JTAG adapter with a CPLD between the
45 * parallel port and the JTAG connection. VHDL code running in the
46 * CPLD significantly accelerates JTAG operations compared to the
47 * bitbanging "Wiggler" style of most parallel port adapters.
51 static uint16_t amt_jtagaccel_port
;
53 /* interface variables
55 static uint8_t aw_control_rst
;
56 static uint8_t aw_control_fsm
= 0x10;
57 static uint8_t aw_control_baudrate
= 0x20;
59 static int rtck_enabled
;
61 #if PARPORT_USE_PPDEV == 1
62 static int device_handle
;
64 static const int addr_mode
= IEEE1284_MODE_EPP
| IEEE1284_ADDR
;
66 /* FIXME do something sane when these ioctl/read/write calls fail. */
72 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
73 assert(__retval >= 0); \
74 __retval = write(device_handle, &val, 1); \
75 assert(__retval >= 0); \
81 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
82 assert(__retval >= 0); \
83 __retval = read(device_handle, &val, 1); \
84 assert(__retval >= 0); \
87 static const int data_mode
= IEEE1284_MODE_EPP
| IEEE1284_DATA
;
93 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
94 assert(__retval >= 0); \
95 __retval = write(device_handle, &val, 1); \
96 assert(__retval >= 0); \
102 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
103 assert(__retval >= 0); \
104 __retval = read(device_handle, &val, 1); \
105 assert(__retval >= 0); \
110 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
111 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
112 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
113 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
115 #endif /* PARPORT_USE_PPDEV */
117 /* tap_move[i][j]: tap movement command to go from state i to state j
118 * 0: Test-Logic-Reset
125 static const uint8_t amt_jtagaccel_tap_move
[6][6][2] = {
126 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
127 { {0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00} }, /* RESET */
128 { {0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00} }, /* IDLE */
129 { {0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRSHIFT */
130 { {0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRPAUSE */
131 { {0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00} }, /* IRSHIFT */
132 { {0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00} }, /* IRPAUSE */
135 static void amt_jtagaccel_reset(int trst
, int srst
)
138 aw_control_rst
|= 0x4;
140 aw_control_rst
&= ~0x4;
143 aw_control_rst
|= 0x1;
145 aw_control_rst
&= ~0x1;
147 AMT_AW(aw_control_rst
);
150 static int amt_jtagaccel_speed(int speed
)
152 aw_control_baudrate
&= 0xf0;
153 aw_control_baudrate
|= speed
& 0x0f;
154 AMT_AW(aw_control_baudrate
);
159 static void amt_jtagaccel_end_state(tap_state_t state
)
161 if (tap_is_state_stable(state
))
162 tap_set_end_state(state
);
164 LOG_ERROR("BUG: %i is not a valid end state", state
);
169 static void amt_wait_scan_busy(void)
175 while (((ar_status
) & 0x80) && (timeout
-- > 0))
178 if (ar_status
& 0x80) {
180 "amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x",
181 (rtck_enabled
) ? "enabled" : "disabled",
187 static void amt_jtagaccel_state_move(void)
189 uint8_t aw_scan_tms_5
;
192 tap_state_t cur_state
= tap_get_state();
193 tap_state_t end_state
= tap_get_end_state();
195 tms_scan
[0] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][0];
196 tms_scan
[1] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][1];
198 aw_scan_tms_5
= 0x40 | (tms_scan
[0] & 0x1f);
199 AMT_AW(aw_scan_tms_5
);
201 int retval
= jtag_get_speed(&jtag_speed
);
202 assert(retval
== ERROR_OK
);
203 if (jtag_speed
> 3 || rtck_enabled
)
204 amt_wait_scan_busy();
206 if (tms_scan
[0] & 0x80) {
207 aw_scan_tms_5
= 0x40 | (tms_scan
[1] & 0x1f);
208 AMT_AW(aw_scan_tms_5
);
209 if (jtag_speed
> 3 || rtck_enabled
)
210 amt_wait_scan_busy();
213 tap_set_state(end_state
);
216 static void amt_jtagaccel_runtest(int num_cycles
)
219 uint8_t aw_scan_tms_5
;
220 uint8_t aw_scan_tms_1to4
;
222 tap_state_t saved_end_state
= tap_get_end_state();
224 /* only do a state_move when we're not already in IDLE */
225 if (tap_get_state() != TAP_IDLE
) {
226 amt_jtagaccel_end_state(TAP_IDLE
);
227 amt_jtagaccel_state_move();
230 while (num_cycles
- i
>= 5) {
231 aw_scan_tms_5
= 0x40;
232 AMT_AW(aw_scan_tms_5
);
236 if (num_cycles
- i
> 0) {
237 aw_scan_tms_1to4
= 0x80 | ((num_cycles
- i
- 1) & 0x3) << 4;
238 AMT_AW(aw_scan_tms_1to4
);
241 amt_jtagaccel_end_state(saved_end_state
);
242 if (tap_get_state() != tap_get_end_state())
243 amt_jtagaccel_state_move();
246 static void amt_jtagaccel_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
)
248 int bits_left
= scan_size
;
250 tap_state_t saved_end_state
= tap_get_end_state();
251 uint8_t aw_tdi_option
;
257 int retval
= jtag_get_speed(&jtag_speed_var
);
258 assert(retval
== ERROR_OK
);
261 amt_jtagaccel_end_state(TAP_IRSHIFT
);
263 amt_jtagaccel_end_state(TAP_DRSHIFT
);
265 /* Only move if we're not already there */
266 if (tap_get_state() != tap_get_end_state())
267 amt_jtagaccel_state_move();
269 amt_jtagaccel_end_state(saved_end_state
);
271 /* handle unaligned bits at the beginning */
272 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_var
> 3 || rtck_enabled
)
279 amt_wait_scan_busy();
281 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
283 dr_tdo
= dr_tdo
>> (8 - ((scan_size
- 1) % 8));
284 buf_set_u32(buffer
, bit_count
, (scan_size
- 1) % 8, dr_tdo
);
287 bit_count
+= (scan_size
- 1) % 8;
288 bits_left
-= (scan_size
- 1) % 8;
291 while (bits_left
- 1 >= 8) {
292 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, 8) & 0xff;
294 if (jtag_speed_var
> 3 || rtck_enabled
)
295 amt_wait_scan_busy();
297 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
299 buf_set_u32(buffer
, bit_count
, 8, dr_tdo
);
307 amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
309 amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
310 aw_tms_scan
= 0x40 | (tms_scan
[0] & 0x1f) | (buf_get_u32(buffer
, bit_count
, 1) << 5);
312 if (jtag_speed_var
> 3 || rtck_enabled
)
313 amt_wait_scan_busy();
315 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
317 dr_tdo
= dr_tdo
>> 7;
318 buf_set_u32(buffer
, bit_count
, 1, dr_tdo
);
321 if (tms_scan
[0] & 0x80) {
322 aw_tms_scan
= 0x40 | (tms_scan
[1] & 0x1f);
324 if (jtag_speed_var
> 3 || rtck_enabled
)
325 amt_wait_scan_busy();
327 tap_set_state(tap_get_end_state());
330 static int amt_jtagaccel_execute_queue(void)
332 struct jtag_command
*cmd
= jtag_command_queue
; /* currently processed command */
338 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
339 * that wasn't handled by a caller-provided error handler
346 #ifdef _DEBUG_JTAG_IO_
347 LOG_DEBUG("reset trst: %i srst %i",
348 cmd
->cmd
.reset
->trst
,
349 cmd
->cmd
.reset
->srst
);
351 if (cmd
->cmd
.reset
->trst
== 1)
352 tap_set_state(TAP_RESET
);
353 amt_jtagaccel_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
356 #ifdef _DEBUG_JTAG_IO_
357 LOG_DEBUG("runtest %i cycles, end in %i",
358 cmd
->cmd
.runtest
->num_cycles
,
359 cmd
->cmd
.runtest
->end_state
);
361 amt_jtagaccel_end_state(cmd
->cmd
.runtest
->end_state
);
362 amt_jtagaccel_runtest(cmd
->cmd
.runtest
->num_cycles
);
365 #ifdef _DEBUG_JTAG_IO_
366 LOG_DEBUG("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
368 amt_jtagaccel_end_state(cmd
->cmd
.statemove
->end_state
);
369 amt_jtagaccel_state_move();
372 #ifdef _DEBUG_JTAG_IO_
373 LOG_DEBUG("scan end in %i", cmd
->cmd
.scan
->end_state
);
375 amt_jtagaccel_end_state(cmd
->cmd
.scan
->end_state
);
376 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
377 type
= jtag_scan_type(cmd
->cmd
.scan
);
378 amt_jtagaccel_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
);
379 if (jtag_read_buffer(buffer
, cmd
->cmd
.scan
) != ERROR_OK
)
380 retval
= ERROR_JTAG_QUEUE_FAILED
;
385 #ifdef _DEBUG_JTAG_IO_
386 LOG_DEBUG("sleep %" PRIi32
, cmd
->cmd
.sleep
->us
);
388 jtag_sleep(cmd
->cmd
.sleep
->us
);
391 LOG_ERROR("BUG: unknown JTAG command type encountered");
400 #if PARPORT_USE_GIVEIO == 1
401 int amt_jtagaccel_get_giveio_access(void)
404 OSVERSIONINFO version
;
406 version
.dwOSVersionInfoSize
= sizeof version
;
407 if (!GetVersionEx(&version
)) {
411 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
414 h
= CreateFile("\\\\.\\giveio",
419 FILE_ATTRIBUTE_NORMAL
,
421 if (h
== INVALID_HANDLE_VALUE
) {
432 static int amt_jtagaccel_init(void)
434 #if PARPORT_USE_PPDEV == 1
437 uint8_t control_port
;
443 #if PARPORT_USE_PPDEV == 1
444 if (device_handle
> 0) {
445 LOG_ERROR("device is already opened");
446 return ERROR_JTAG_INIT_FAILED
;
449 snprintf(buffer
, 256, "/dev/parport%d", amt_jtagaccel_port
);
450 device_handle
= open(buffer
, O_RDWR
);
452 if (device_handle
< 0) {
454 "cannot open device. check it exists and that user read and write rights are set");
455 return ERROR_JTAG_INIT_FAILED
;
458 i
= ioctl(device_handle
, PPCLAIM
);
460 LOG_ERROR("cannot claim device");
461 return ERROR_JTAG_INIT_FAILED
;
464 i
= IEEE1284_MODE_EPP
;
465 i
= ioctl(device_handle
, PPSETMODE
, &i
);
467 LOG_ERROR(" cannot set compatible mode to device");
468 return ERROR_JTAG_INIT_FAILED
;
472 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
475 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
478 if (amt_jtagaccel_port
== 0) {
479 amt_jtagaccel_port
= 0x378;
480 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
483 #if PARPORT_USE_GIVEIO == 1
484 if (amt_jtagaccel_get_giveio_access() != 0) {
485 #else /* PARPORT_USE_GIVEIO */
486 if (ioperm(amt_jtagaccel_port
, 5, 1) != 0) {
487 #endif /* PARPORT_USE_GIVEIO */
488 LOG_ERROR("missing privileges for direct i/o");
489 return ERROR_JTAG_INIT_FAILED
;
494 status_port
= inb(amt_jtagaccel_port
+ 1);
495 outb(status_port
| 0x1, amt_jtagaccel_port
+ 1);
498 outb(0x00, amt_jtagaccel_port
+ 2);
499 outb(0x04, amt_jtagaccel_port
+ 2);
503 /* set RTCK enable bit */
504 aw_control_fsm
|= 0x02;
507 /* enable JTAG port */
508 aw_control_fsm
|= 0x04;
509 AMT_AW(aw_control_fsm
);
511 enum reset_types jtag_reset_config
= jtag_get_reset_config();
512 if (jtag_reset_config
& RESET_TRST_OPEN_DRAIN
)
513 aw_control_rst
&= ~0x8;
515 aw_control_rst
|= 0x8;
517 if (jtag_reset_config
& RESET_SRST_PUSH_PULL
)
518 aw_control_rst
&= ~0x2;
520 aw_control_rst
|= 0x2;
522 amt_jtagaccel_reset(0, 0);
524 /* read status register */
526 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status
);
531 static int amt_jtagaccel_quit(void)
537 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command
)
540 /* only if the port wasn't overwritten by cmdline */
541 if (amt_jtagaccel_port
== 0) {
543 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
544 amt_jtagaccel_port
= port
;
546 LOG_ERROR("The parport port was already configured!");
551 command_print(CMD_CTX
, "parport port = %u", amt_jtagaccel_port
);
556 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command
)
559 command_print(CMD_CTX
,
560 "amt_jtagaccel RTCK feature %s",
561 (rtck_enabled
) ? "enabled" : "disabled");
564 if (strcmp(CMD_ARGV
[0], "enabled") == 0)
573 static const struct command_registration amtjtagaccel_command_handlers
[] = {
575 .name
= "parport_port",
576 .handler
= &amt_jtagaccel_handle_parport_port_command
,
577 .mode
= COMMAND_CONFIG
,
578 .help
= "configure or display the parallel port to use",
579 .usage
= "[port_num]",
583 * @todo Remove this "rtck" command; just use the standard
584 * mechanism to enable/disable adaptive clocking. First
585 * implement the standard mechanism and deprecate "rtck";
586 * after a year or so, it'll be safe to remove this.
589 .handler
= &amt_jtagaccel_handle_rtck_command
,
590 .mode
= COMMAND_CONFIG
,
591 .help
= "configure or display RTCK support",
592 .usage
= "[enable|disable]",
594 COMMAND_REGISTRATION_DONE
597 struct jtag_interface amt_jtagaccel_interface
= {
598 .name
= "amt_jtagaccel",
599 .commands
= amtjtagaccel_command_handlers
,
601 .init
= amt_jtagaccel_init
,
602 .quit
= amt_jtagaccel_quit
,
603 .speed
= amt_jtagaccel_speed
,
604 .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)