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

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)