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

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)