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

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)