f005be65d638a145bba0a91232eda738faf97de6
[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 .support_pathmove = 0,
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 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 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 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 void amt_jtagaccel_end_state(state)
165 {
166 if (tap_move_map[state] != -1)
167 end_state = state;
168 else
169 {
170 ERROR("BUG: %i is not a valid end state", state);
171 exit(-1);
172 }
173 }
174
175 void amt_wait_scan_busy()
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 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 void amt_jtagaccel_state_move(void)
192 {
193 u8 aw_scan_tms_5;
194 u8 tms_scan[2];
195
196 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][0];
197 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][1];
198
199 aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f);
200 AMT_AW(aw_scan_tms_5);
201 if (jtag_speed > 3 || rtck_enabled)
202 amt_wait_scan_busy();
203
204 if (tms_scan[0] & 0x80)
205 {
206 aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
207 AMT_AW(aw_scan_tms_5);
208 if (jtag_speed > 3 || rtck_enabled)
209 amt_wait_scan_busy();
210 }
211
212 cur_state = end_state;
213 }
214
215 void amt_jtagaccel_runtest(int num_cycles)
216 {
217 int i = 0;
218 u8 aw_scan_tms_5;
219 u8 aw_scan_tms_1to4;
220
221 enum tap_state saved_end_state = end_state;
222
223 /* only do a state_move when we're not already in RTI */
224 if (cur_state != TAP_RTI)
225 {
226 amt_jtagaccel_end_state(TAP_RTI);
227 amt_jtagaccel_state_move();
228 }
229
230 while (num_cycles - i >= 5)
231 {
232 aw_scan_tms_5 = 0x40;
233 AMT_AW(aw_scan_tms_5);
234 i += 5;
235 }
236
237 if (num_cycles - i > 0)
238 {
239 aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
240 AMT_AW(aw_scan_tms_1to4);
241 }
242
243 amt_jtagaccel_end_state(saved_end_state);
244 if (cur_state != end_state)
245 amt_jtagaccel_state_move();
246 }
247
248 void amt_jtagaccel_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
249 {
250 int bits_left = scan_size;
251 int bit_count = 0;
252 enum tap_state saved_end_state = end_state;
253 u8 aw_tdi_option;
254 u8 dw_tdi_scan;
255 u8 dr_tdo;
256 u8 aw_tms_scan;
257 u8 tms_scan[2];
258
259 if (ir_scan)
260 amt_jtagaccel_end_state(TAP_SI);
261 else
262 amt_jtagaccel_end_state(TAP_SD);
263
264 amt_jtagaccel_state_move();
265 amt_jtagaccel_end_state(saved_end_state);
266
267 /* handle unaligned bits at the beginning */
268 if ((scan_size - 1) % 8)
269 {
270 aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
271 AMT_AW(aw_tdi_option);
272
273 dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
274 AMT_DW(dw_tdi_scan);
275 if (jtag_speed > 3 || rtck_enabled)
276 amt_wait_scan_busy();
277
278 if ((type == SCAN_IN) || (type == SCAN_IO))
279 {
280 AMT_DR(dr_tdo);
281 dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
282 buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
283 }
284
285 bit_count += (scan_size - 1) % 8;
286 bits_left -= (scan_size - 1) % 8;
287 }
288
289 while (bits_left - 1 >= 8)
290 {
291 dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
292 AMT_DW(dw_tdi_scan);
293 if (jtag_speed > 3 || rtck_enabled)
294 amt_wait_scan_busy();
295
296 if ((type == SCAN_IN) || (type == SCAN_IO))
297 {
298 AMT_DR(dr_tdo);
299 buf_set_u32(buffer, bit_count, 8, dr_tdo);
300 }
301
302 bit_count += 8;
303 bits_left -= 8;
304 }
305
306 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][0];
307 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][1];
308 aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
309 AMT_AW(aw_tms_scan);
310 if (jtag_speed > 3 || rtck_enabled)
311 amt_wait_scan_busy();
312
313 if ((type == SCAN_IN) || (type == SCAN_IO))
314 {
315 AMT_DR(dr_tdo);
316 dr_tdo = dr_tdo >> 7;
317 buf_set_u32(buffer, bit_count, 1, dr_tdo);
318 }
319
320 if (tms_scan[0] & 0x80)
321 {
322 aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
323 AMT_AW(aw_tms_scan);
324 if (jtag_speed > 3 || rtck_enabled)
325 amt_wait_scan_busy();
326 }
327 cur_state = end_state;
328 }
329
330 int amt_jtagaccel_execute_queue(void)
331 {
332 jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
333 int scan_size;
334 enum scan_type type;
335 u8 *buffer;
336 int retval;
337
338 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
339 * that wasn't handled by a caller-provided error handler
340 */
341 retval = ERROR_OK;
342
343 while (cmd)
344 {
345 switch (cmd->type)
346 {
347 case JTAG_END_STATE:
348 #ifdef _DEBUG_JTAG_IO_
349 DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
350 #endif
351 if (cmd->cmd.end_state->end_state != -1)
352 amt_jtagaccel_end_state(cmd->cmd.end_state->end_state);
353 break;
354 case JTAG_RESET:
355 #ifdef _DEBUG_JTAG_IO_
356 DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
357 #endif
358 if (cmd->cmd.reset->trst == 1)
359 {
360 cur_state = TAP_TLR;
361 }
362 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
363 break;
364 case JTAG_RUNTEST:
365 #ifdef _DEBUG_JTAG_IO_
366 DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
367 #endif
368 if (cmd->cmd.runtest->end_state != -1)
369 amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
370 amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
371 break;
372 case JTAG_STATEMOVE:
373 #ifdef _DEBUG_JTAG_IO_
374 DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
375 #endif
376 if (cmd->cmd.statemove->end_state != -1)
377 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
378 amt_jtagaccel_state_move();
379 break;
380 case JTAG_SCAN:
381 #ifdef _DEBUG_JTAG_IO_
382 DEBUG("scan end in %i", cmd->cmd.scan->end_state);
383 #endif
384 if (cmd->cmd.scan->end_state != -1)
385 amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
386 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
387 type = jtag_scan_type(cmd->cmd.scan);
388 amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
389 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
390 retval = ERROR_JTAG_QUEUE_FAILED;
391 if (buffer)
392 free(buffer);
393 break;
394 case JTAG_SLEEP:
395 #ifdef _DEBUG_JTAG_IO_
396 DEBUG("sleep %i", cmd->cmd.sleep->us);
397 #endif
398 jtag_sleep(cmd->cmd.sleep->us);
399 break;
400 default:
401 ERROR("BUG: unknown JTAG command type encountered");
402 exit(-1);
403 }
404 cmd = cmd->next;
405 }
406
407 return retval;
408 }
409
410 #if PARPORT_USE_GIVEIO == 1
411 int amt_jtagaccel_get_giveio_access()
412 {
413 HANDLE h;
414 OSVERSIONINFO version;
415
416 version.dwOSVersionInfoSize = sizeof version;
417 if (!GetVersionEx( &version )) {
418 errno = EINVAL;
419 return -1;
420 }
421 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
422 return 0;
423
424 h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
425 if (h == INVALID_HANDLE_VALUE) {
426 errno = ENODEV;
427 return -1;
428 }
429
430 CloseHandle( h );
431
432 return 0;
433 }
434 #endif
435
436 int amt_jtagaccel_init(void)
437 {
438 #if PARPORT_USE_PPDEV == 1
439 char buffer[256];
440 int i = 0;
441 u8 control_port;
442 #else
443 u8 status_port;
444 #endif
445 u8 ar_status;
446
447 #if PARPORT_USE_PPDEV == 1
448 if (device_handle > 0)
449 {
450 ERROR("device is already opened");
451 return ERROR_JTAG_INIT_FAILED;
452 }
453
454 snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
455 device_handle = open(buffer, O_RDWR);
456
457 if (device_handle < 0)
458 {
459 ERROR("cannot open device. check it exists and that user read and write rights are set");
460 return ERROR_JTAG_INIT_FAILED;
461 }
462
463 i = ioctl(device_handle, PPCLAIM);
464 if (i < 0)
465 {
466 ERROR("cannot claim device");
467 return ERROR_JTAG_INIT_FAILED;
468 }
469
470 i = IEEE1284_MODE_EPP;
471 i = ioctl(device_handle, PPSETMODE, & i);
472 if (i < 0)
473 {
474 ERROR(" cannot set compatible mode to device");
475 return ERROR_JTAG_INIT_FAILED;
476 }
477
478 control_port = 0x00;
479 i = ioctl(device_handle, PPWCONTROL, &control_port);
480
481 control_port = 0x04;
482 i = ioctl(device_handle, PPWCONTROL, &control_port);
483
484 #else
485 if (amt_jtagaccel_port == 0)
486 {
487 amt_jtagaccel_port = 0x378;
488 WARNING("No parport port specified, using default '0x378' (LPT1)");
489 }
490
491 #if PARPORT_USE_GIVEIO == 1
492 if (amt_jtagaccel_get_giveio_access() != 0) {
493 #else /* PARPORT_USE_GIVEIO */
494 if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
495 #endif /* PARPORT_USE_GIVEIO */
496 ERROR("missing privileges for direct i/o");
497 return ERROR_JTAG_INIT_FAILED;
498 }
499
500 /* prepare epp port */
501 /* clear timeout */
502 status_port = inb(amt_jtagaccel_port + 1);
503 outb(status_port | 0x1, amt_jtagaccel_port + 1);
504
505 /* reset epp port */
506 outb(0x00, amt_jtagaccel_port + 2);
507 outb(0x04, amt_jtagaccel_port + 2);
508 #endif
509
510 if (rtck_enabled)
511 {
512 /* set RTCK enable bit */
513 aw_control_fsm |= 0x02;
514 }
515
516 /* enable JTAG port */
517 aw_control_fsm |= 0x04;
518 AMT_AW(aw_control_fsm);
519
520 amt_jtagaccel_speed(jtag_speed);
521
522 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
523 aw_control_rst &= ~0x8;
524 else
525 aw_control_rst |= 0x8;
526
527 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
528 aw_control_rst &= ~0x2;
529 else
530 aw_control_rst |= 0x2;
531
532 amt_jtagaccel_reset(0, 0);
533
534 /* read status register */
535 AMT_AR(ar_status);
536 DEBUG("AR_STATUS: 0x%2.2x", ar_status);
537
538 return ERROR_OK;
539 }
540
541 int amt_jtagaccel_quit(void)
542 {
543
544 return ERROR_OK;
545 }
546
547 int amt_jtagaccel_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
548 {
549 if (argc == 0)
550 return ERROR_OK;
551
552 /* only if the port wasn't overwritten by cmdline */
553 if (amt_jtagaccel_port == 0)
554 amt_jtagaccel_port = strtoul(args[0], NULL, 0);
555
556 return ERROR_OK;
557 }
558
559 int amt_jtagaccel_handle_rtck_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
560 {
561 if (argc == 0)
562 {
563 command_print(cmd_ctx, "amt_jtagaccel RTCK feature %s", (rtck_enabled) ? "enabled" : "disabled");
564 return ERROR_OK;
565 }
566 else
567 {
568 if (strcmp(args[0], "enabled") == 0)
569 {
570 rtck_enabled = 1;
571 }
572 else
573 {
574 rtck_enabled = 0;
575 }
576 }
577
578 return ERROR_OK;
579 }

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)