2db90935f309232a46f126d1d2c8543357a2d68f
[openocd.git] / src / jtag / amt_jtagaccel.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "replacements.h"
25
26 #include "jtag.h"
27
28 /* system includes */
29
30 #ifdef _WIN32
31 #include "errno.h"
32 #endif /* _WIN32 */
33
34 #include <string.h>
35 #include <stdlib.h>
36
37 #if PARPORT_USE_PPDEV == 1
38 #include <linux/parport.h>
39 #include <linux/ppdev.h>
40 #include <fcntl.h>
41 #include <sys/ioctl.h>
42 #include <unistd.h>
43 #else /* not PARPORT_USE_PPDEV */
44 #ifndef _WIN32
45 #include <sys/io.h>
46 #endif
47 #endif
48
49 #if PARPORT_USE_GIVEIO == 1
50 #if IS_CYGWIN == 1
51 #include <windows.h>
52 #include <errno.h>
53 #endif
54 #endif
55
56 #include "log.h"
57
58 /* configuration */
59 static u16 amt_jtagaccel_port;
60
61 /* interface variables
62 */
63 static u8 aw_control_rst = 0x00;
64 static u8 aw_control_fsm = 0x10;
65 static u8 aw_control_baudrate = 0x20;
66
67 static int rtck_enabled = 0;
68
69 #if PARPORT_USE_PPDEV == 1
70 static int device_handle;
71
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)
75
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)
79
80 #else
81
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)
86
87 #endif // PARPORT_USE_PPDEV
88
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);
94
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);
97
98 /* tap_move[i][j]: tap movement command to go from state i to state j
99 * 0: Test-Logic-Reset
100 * 1: Run-Test/Idle
101 * 2: Shift-DR
102 * 3: Pause-DR
103 * 4: Shift-IR
104 * 5: Pause-IR
105 */
106 static u8 amt_jtagaccel_tap_move[6][6][2] =
107 {
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 */
115 };
116
117
118 jtag_interface_t amt_jtagaccel_interface =
119 {
120 .name = "amt_jtagaccel",
121
122 .execute_queue = amt_jtagaccel_execute_queue,
123
124 .speed = amt_jtagaccel_speed,
125 .register_commands = amt_jtagaccel_register_commands,
126 .init = amt_jtagaccel_init,
127 .quit = amt_jtagaccel_quit,
128 };
129
130 static int amt_jtagaccel_register_commands(struct command_context_s *cmd_ctx)
131 {
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);
136
137 return ERROR_OK;
138 }
139
140 static void amt_jtagaccel_reset(int trst, int srst)
141 {
142 if (trst == 1)
143 aw_control_rst |= 0x4;
144 else if (trst == 0)
145 aw_control_rst &= ~0x4;
146
147 if (srst == 1)
148 aw_control_rst |= 0x1;
149 else if (srst == 0)
150 aw_control_rst &= ~0x1;
151
152 AMT_AW(aw_control_rst);
153 }
154
155 static int amt_jtagaccel_speed(int speed)
156 {
157 aw_control_baudrate &= 0xf0;
158 aw_control_baudrate |= speed & 0x0f;
159 AMT_AW(aw_control_baudrate);
160
161 return ERROR_OK;
162 }
163
164 static void amt_jtagaccel_end_state(tap_state_t state)
165 {
166 if (tap_is_state_stable(state))
167 tap_set_end_state(state);
168 else
169 {
170 LOG_ERROR("BUG: %i is not a valid end state", state);
171 exit(-1);
172 }
173 }
174
175 static void amt_wait_scan_busy(void)
176 {
177 int timeout = 4096;
178 u8 ar_status;
179
180 AMT_AR(ar_status);
181 while (((ar_status) & 0x80) && (timeout-- > 0))
182 AMT_AR(ar_status);
183
184 if (ar_status & 0x80)
185 {
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);
187 exit(-1);
188 }
189 }
190
191 static void amt_jtagaccel_state_move(void)
192 {
193 u8 aw_scan_tms_5;
194 u8 tms_scan[2];
195
196 tap_state_t cur_state = tap_get_state();
197 tap_state_t end_state = tap_get_end_state();
198
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];
201
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();
206
207 if (tms_scan[0] & 0x80)
208 {
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();
213 }
214
215 tap_set_state(end_state);
216 }
217
218 static void amt_jtagaccel_runtest(int num_cycles)
219 {
220 int i = 0;
221 u8 aw_scan_tms_5;
222 u8 aw_scan_tms_1to4;
223
224 tap_state_t saved_end_state = tap_get_end_state();
225
226 /* only do a state_move when we're not already in IDLE */
227 if (tap_get_state() != TAP_IDLE)
228 {
229 amt_jtagaccel_end_state(TAP_IDLE);
230 amt_jtagaccel_state_move();
231 }
232
233 while (num_cycles - i >= 5)
234 {
235 aw_scan_tms_5 = 0x40;
236 AMT_AW(aw_scan_tms_5);
237 i += 5;
238 }
239
240 if (num_cycles - i > 0)
241 {
242 aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
243 AMT_AW(aw_scan_tms_1to4);
244 }
245
246 amt_jtagaccel_end_state(saved_end_state);
247 if (tap_get_state() != tap_get_end_state())
248 amt_jtagaccel_state_move();
249 }
250
251 static void amt_jtagaccel_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
252 {
253 int bits_left = scan_size;
254 int bit_count = 0;
255 tap_state_t saved_end_state = tap_get_end_state();
256 u8 aw_tdi_option;
257 u8 dw_tdi_scan;
258 u8 dr_tdo;
259 u8 aw_tms_scan;
260 u8 tms_scan[2];
261
262 if (ir_scan)
263 amt_jtagaccel_end_state(TAP_IRSHIFT);
264 else
265 amt_jtagaccel_end_state(TAP_DRSHIFT);
266
267 amt_jtagaccel_state_move();
268 amt_jtagaccel_end_state(saved_end_state);
269
270 /* handle unaligned bits at the beginning */
271 if ((scan_size - 1) % 8)
272 {
273 aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
274 AMT_AW(aw_tdi_option);
275
276 dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
277 AMT_DW(dw_tdi_scan);
278 if (jtag_speed > 3 || rtck_enabled)
279 amt_wait_scan_busy();
280
281 if ((type == SCAN_IN) || (type == SCAN_IO))
282 {
283 AMT_DR(dr_tdo);
284 dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
285 buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
286 }
287
288 bit_count += (scan_size - 1) % 8;
289 bits_left -= (scan_size - 1) % 8;
290 }
291
292 while (bits_left - 1 >= 8)
293 {
294 dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
295 AMT_DW(dw_tdi_scan);
296 if (jtag_speed > 3 || rtck_enabled)
297 amt_wait_scan_busy();
298
299 if ((type == SCAN_IN) || (type == SCAN_IO))
300 {
301 AMT_DR(dr_tdo);
302 buf_set_u32(buffer, bit_count, 8, dr_tdo);
303 }
304
305 bit_count += 8;
306 bits_left -= 8;
307 }
308
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);
312 AMT_AW(aw_tms_scan);
313 if (jtag_speed > 3 || rtck_enabled)
314 amt_wait_scan_busy();
315
316 if ((type == SCAN_IN) || (type == SCAN_IO))
317 {
318 AMT_DR(dr_tdo);
319 dr_tdo = dr_tdo >> 7;
320 buf_set_u32(buffer, bit_count, 1, dr_tdo);
321 }
322
323 if (tms_scan[0] & 0x80)
324 {
325 aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
326 AMT_AW(aw_tms_scan);
327 if (jtag_speed > 3 || rtck_enabled)
328 amt_wait_scan_busy();
329 }
330 tap_set_state(tap_get_end_state());
331 }
332
333 static int amt_jtagaccel_execute_queue(void)
334 {
335 jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
336 int scan_size;
337 enum scan_type type;
338 u8 *buffer;
339 int retval;
340
341 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
342 * that wasn't handled by a caller-provided error handler
343 */
344 retval = ERROR_OK;
345
346 while (cmd)
347 {
348 switch (cmd->type)
349 {
350 case JTAG_END_STATE:
351 #ifdef _DEBUG_JTAG_IO_
352 LOG_DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
353 #endif
354 if (cmd->cmd.end_state->end_state != TAP_INVALID)
355 amt_jtagaccel_end_state(cmd->cmd.end_state->end_state);
356 break;
357 case JTAG_RESET:
358 #ifdef _DEBUG_JTAG_IO_
359 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
360 #endif
361 if (cmd->cmd.reset->trst == 1)
362 {
363 tap_set_state(TAP_RESET);
364 }
365 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
366 break;
367 case JTAG_RUNTEST:
368 #ifdef _DEBUG_JTAG_IO_
369 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
370 #endif
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);
374 break;
375 case JTAG_STATEMOVE:
376 #ifdef _DEBUG_JTAG_IO_
377 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
378 #endif
379 if (cmd->cmd.statemove->end_state != TAP_INVALID)
380 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
381 amt_jtagaccel_state_move();
382 break;
383 case JTAG_SCAN:
384 #ifdef _DEBUG_JTAG_IO_
385 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
386 #endif
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;
394 if (buffer)
395 free(buffer);
396 break;
397 case JTAG_SLEEP:
398 #ifdef _DEBUG_JTAG_IO_
399 LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
400 #endif
401 jtag_sleep(cmd->cmd.sleep->us);
402 break;
403 default:
404 LOG_ERROR("BUG: unknown JTAG command type encountered");
405 exit(-1);
406 }
407 cmd = cmd->next;
408 }
409
410 return retval;
411 }
412
413 #if PARPORT_USE_GIVEIO == 1
414 int amt_jtagaccel_get_giveio_access(void)
415 {
416 HANDLE h;
417 OSVERSIONINFO version;
418
419 version.dwOSVersionInfoSize = sizeof version;
420 if (!GetVersionEx( &version )) {
421 errno = EINVAL;
422 return -1;
423 }
424 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
425 return 0;
426
427 h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
428 if (h == INVALID_HANDLE_VALUE) {
429 errno = ENODEV;
430 return -1;
431 }
432
433 CloseHandle( h );
434
435 return 0;
436 }
437 #endif
438
439 static int amt_jtagaccel_init(void)
440 {
441 #if PARPORT_USE_PPDEV == 1
442 char buffer[256];
443 int i = 0;
444 u8 control_port;
445 #else
446 u8 status_port;
447 #endif
448 u8 ar_status;
449
450 #if PARPORT_USE_PPDEV == 1
451 if (device_handle > 0)
452 {
453 LOG_ERROR("device is already opened");
454 return ERROR_JTAG_INIT_FAILED;
455 }
456
457 snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
458 device_handle = open(buffer, O_RDWR);
459
460 if (device_handle < 0)
461 {
462 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
463 return ERROR_JTAG_INIT_FAILED;
464 }
465
466 i = ioctl(device_handle, PPCLAIM);
467 if (i < 0)
468 {
469 LOG_ERROR("cannot claim device");
470 return ERROR_JTAG_INIT_FAILED;
471 }
472
473 i = IEEE1284_MODE_EPP;
474 i = ioctl(device_handle, PPSETMODE, & i);
475 if (i < 0)
476 {
477 LOG_ERROR(" cannot set compatible mode to device");
478 return ERROR_JTAG_INIT_FAILED;
479 }
480
481 control_port = 0x00;
482 i = ioctl(device_handle, PPWCONTROL, &control_port);
483
484 control_port = 0x04;
485 i = ioctl(device_handle, PPWCONTROL, &control_port);
486
487 #else
488 if (amt_jtagaccel_port == 0)
489 {
490 amt_jtagaccel_port = 0x378;
491 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
492 }
493
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;
501 }
502
503 /* prepare epp port */
504 /* clear timeout */
505 status_port = inb(amt_jtagaccel_port + 1);
506 outb(status_port | 0x1, amt_jtagaccel_port + 1);
507
508 /* reset epp port */
509 outb(0x00, amt_jtagaccel_port + 2);
510 outb(0x04, amt_jtagaccel_port + 2);
511 #endif
512
513 if (rtck_enabled)
514 {
515 /* set RTCK enable bit */
516 aw_control_fsm |= 0x02;
517 }
518
519 /* enable JTAG port */
520 aw_control_fsm |= 0x04;
521 AMT_AW(aw_control_fsm);
522
523 amt_jtagaccel_speed(jtag_speed);
524
525 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
526 aw_control_rst &= ~0x8;
527 else
528 aw_control_rst |= 0x8;
529
530 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
531 aw_control_rst &= ~0x2;
532 else
533 aw_control_rst |= 0x2;
534
535 amt_jtagaccel_reset(0, 0);
536
537 /* read status register */
538 AMT_AR(ar_status);
539 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status);
540
541 return ERROR_OK;
542 }
543
544 static int amt_jtagaccel_quit(void)
545 {
546
547 return ERROR_OK;
548 }
549
550 static int amt_jtagaccel_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
551 {
552 if (argc == 0)
553 return ERROR_OK;
554
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);
558
559 return ERROR_OK;
560 }
561
562 static int amt_jtagaccel_handle_rtck_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
563 {
564 if (argc == 0)
565 {
566 command_print(cmd_ctx, "amt_jtagaccel RTCK feature %s", (rtck_enabled) ? "enabled" : "disabled");
567 return ERROR_OK;
568 }
569 else
570 {
571 if (strcmp(args[0], "enabled") == 0)
572 {
573 rtck_enabled = 1;
574 }
575 else
576 {
577 rtck_enabled = 0;
578 }
579 }
580
581 return ERROR_OK;
582 }

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)