remove unused JTAG_END_STATE
[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(bool 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_RESET:
336 #ifdef _DEBUG_JTAG_IO_
337 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
338 #endif
339 if (cmd->cmd.reset->trst == 1)
340 {
341 tap_set_state(TAP_RESET);
342 }
343 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
344 break;
345 case JTAG_RUNTEST:
346 #ifdef _DEBUG_JTAG_IO_
347 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
348 #endif
349 if (cmd->cmd.runtest->end_state != TAP_INVALID)
350 amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
351 amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
352 break;
353 case JTAG_STATEMOVE:
354 #ifdef _DEBUG_JTAG_IO_
355 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
356 #endif
357 if (cmd->cmd.statemove->end_state != TAP_INVALID)
358 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
359 amt_jtagaccel_state_move();
360 break;
361 case JTAG_SCAN:
362 #ifdef _DEBUG_JTAG_IO_
363 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
364 #endif
365 if (cmd->cmd.scan->end_state != TAP_INVALID)
366 amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
367 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
368 type = jtag_scan_type(cmd->cmd.scan);
369 amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
370 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
371 retval = ERROR_JTAG_QUEUE_FAILED;
372 if (buffer)
373 free(buffer);
374 break;
375 case JTAG_SLEEP:
376 #ifdef _DEBUG_JTAG_IO_
377 LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
378 #endif
379 jtag_sleep(cmd->cmd.sleep->us);
380 break;
381 default:
382 LOG_ERROR("BUG: unknown JTAG command type encountered");
383 exit(-1);
384 }
385 cmd = cmd->next;
386 }
387
388 return retval;
389 }
390
391 #if PARPORT_USE_GIVEIO == 1
392 int amt_jtagaccel_get_giveio_access(void)
393 {
394 HANDLE h;
395 OSVERSIONINFO version;
396
397 version.dwOSVersionInfoSize = sizeof version;
398 if (!GetVersionEx( &version )) {
399 errno = EINVAL;
400 return -1;
401 }
402 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
403 return 0;
404
405 h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
406 if (h == INVALID_HANDLE_VALUE) {
407 errno = ENODEV;
408 return -1;
409 }
410
411 CloseHandle( h );
412
413 return 0;
414 }
415 #endif
416
417 static int amt_jtagaccel_init(void)
418 {
419 #if PARPORT_USE_PPDEV == 1
420 char buffer[256];
421 int i = 0;
422 u8 control_port;
423 #else
424 u8 status_port;
425 #endif
426 u8 ar_status;
427
428 #if PARPORT_USE_PPDEV == 1
429 if (device_handle > 0)
430 {
431 LOG_ERROR("device is already opened");
432 return ERROR_JTAG_INIT_FAILED;
433 }
434
435 snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
436 device_handle = open(buffer, O_RDWR);
437
438 if (device_handle < 0)
439 {
440 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
441 return ERROR_JTAG_INIT_FAILED;
442 }
443
444 i = ioctl(device_handle, PPCLAIM);
445 if (i < 0)
446 {
447 LOG_ERROR("cannot claim device");
448 return ERROR_JTAG_INIT_FAILED;
449 }
450
451 i = IEEE1284_MODE_EPP;
452 i = ioctl(device_handle, PPSETMODE, & i);
453 if (i < 0)
454 {
455 LOG_ERROR(" cannot set compatible mode to device");
456 return ERROR_JTAG_INIT_FAILED;
457 }
458
459 control_port = 0x00;
460 i = ioctl(device_handle, PPWCONTROL, &control_port);
461
462 control_port = 0x04;
463 i = ioctl(device_handle, PPWCONTROL, &control_port);
464
465 #else
466 if (amt_jtagaccel_port == 0)
467 {
468 amt_jtagaccel_port = 0x378;
469 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
470 }
471
472 #if PARPORT_USE_GIVEIO == 1
473 if (amt_jtagaccel_get_giveio_access() != 0) {
474 #else /* PARPORT_USE_GIVEIO */
475 if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
476 #endif /* PARPORT_USE_GIVEIO */
477 LOG_ERROR("missing privileges for direct i/o");
478 return ERROR_JTAG_INIT_FAILED;
479 }
480
481 /* prepare epp port */
482 /* clear timeout */
483 status_port = inb(amt_jtagaccel_port + 1);
484 outb(status_port | 0x1, amt_jtagaccel_port + 1);
485
486 /* reset epp port */
487 outb(0x00, amt_jtagaccel_port + 2);
488 outb(0x04, amt_jtagaccel_port + 2);
489 #endif
490
491 if (rtck_enabled)
492 {
493 /* set RTCK enable bit */
494 aw_control_fsm |= 0x02;
495 }
496
497 /* enable JTAG port */
498 aw_control_fsm |= 0x04;
499 AMT_AW(aw_control_fsm);
500
501 amt_jtagaccel_speed(jtag_speed);
502
503 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
504 aw_control_rst &= ~0x8;
505 else
506 aw_control_rst |= 0x8;
507
508 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
509 aw_control_rst &= ~0x2;
510 else
511 aw_control_rst |= 0x2;
512
513 amt_jtagaccel_reset(0, 0);
514
515 /* read status register */
516 AMT_AR(ar_status);
517 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status);
518
519 return ERROR_OK;
520 }
521
522 static int amt_jtagaccel_quit(void)
523 {
524
525 return ERROR_OK;
526 }
527
528 static int amt_jtagaccel_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
529 {
530 if (argc == 0)
531 return ERROR_OK;
532
533 /* only if the port wasn't overwritten by cmdline */
534 if (amt_jtagaccel_port == 0)
535 amt_jtagaccel_port = strtoul(args[0], NULL, 0);
536
537 return ERROR_OK;
538 }
539
540 static int amt_jtagaccel_handle_rtck_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
541 {
542 if (argc == 0)
543 {
544 command_print(cmd_ctx, "amt_jtagaccel RTCK feature %s", (rtck_enabled) ? "enabled" : "disabled");
545 return ERROR_OK;
546 }
547 else
548 {
549 if (strcmp(args[0], "enabled") == 0)
550 {
551 rtck_enabled = 1;
552 }
553 else
554 {
555 rtck_enabled = 0;
556 }
557 }
558
559 return ERROR_OK;
560 }

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)