Remove whitespace that occurs after '('.
[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 "interface.h"
25 #include "commands.h"
26
27
28 #if PARPORT_USE_PPDEV == 1
29 #include <linux/parport.h>
30 #include <linux/ppdev.h>
31 #include <sys/ioctl.h>
32 #else /* not PARPORT_USE_PPDEV */
33 #ifndef _WIN32
34 #include <sys/io.h>
35 #endif
36 #endif
37
38 #if PARPORT_USE_GIVEIO == 1
39 #if IS_CYGWIN == 1
40 #include <windows.h>
41 #endif
42 #endif
43
44 /* configuration */
45 static uint16_t amt_jtagaccel_port;
46
47 /* interface variables
48 */
49 static uint8_t aw_control_rst = 0x00;
50 static uint8_t aw_control_fsm = 0x10;
51 static uint8_t aw_control_baudrate = 0x20;
52
53 static int rtck_enabled = 0;
54
55 #if PARPORT_USE_PPDEV == 1
56 static int device_handle;
57
58 static int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR ;
59 #define AMT_AW(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); write(device_handle, &val, 1); } while (0)
60 #define AMT_AR(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); read(device_handle, &val, 1); } while (0)
61
62 static int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA ;
63 #define AMT_DW(val) do { ioctl(device_handle, PPSETMODE, &data_mode); write(device_handle, &val, 1); } while (0)
64 #define AMT_DR(val) do { ioctl(device_handle, PPSETMODE, &data_mode); read(device_handle, &val, 1); } while (0)
65
66 #else
67
68 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
69 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
70 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
71 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
72
73 #endif // PARPORT_USE_PPDEV
74
75 static int amt_jtagaccel_execute_queue(void);
76 static int amt_jtagaccel_register_commands(struct command_context_s *cmd_ctx);
77 static int amt_jtagaccel_speed(int speed);
78 static int amt_jtagaccel_init(void);
79 static int amt_jtagaccel_quit(void);
80
81 static int amt_jtagaccel_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
82 static int amt_jtagaccel_handle_rtck_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
83
84 /* tap_move[i][j]: tap movement command to go from state i to state j
85 * 0: Test-Logic-Reset
86 * 1: Run-Test/Idle
87 * 2: Shift-DR
88 * 3: Pause-DR
89 * 4: Shift-IR
90 * 5: Pause-IR
91 */
92 static uint8_t amt_jtagaccel_tap_move[6][6][2] =
93 {
94 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
95 {{0x1f, 0x00}, {0x0f, 0x00}, {0x8a, 0x04}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00}}, /* RESET */
96 {{0x1f, 0x00}, {0x00, 0x00}, {0x85, 0x08}, {0x05, 0x00}, {0x8b, 0x08}, {0x0b, 0x00}}, /* IDLE */
97 {{0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRSHIFT */
98 {{0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRPAUSE */
99 {{0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00}}, /* IRSHIFT */
100 {{0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00}}, /* IRPAUSE */
101 };
102
103
104 jtag_interface_t amt_jtagaccel_interface =
105 {
106 .name = "amt_jtagaccel",
107
108 .execute_queue = amt_jtagaccel_execute_queue,
109
110 .speed = amt_jtagaccel_speed,
111 .register_commands = amt_jtagaccel_register_commands,
112 .init = amt_jtagaccel_init,
113 .quit = amt_jtagaccel_quit,
114 };
115
116 static int amt_jtagaccel_register_commands(struct command_context_s *cmd_ctx)
117 {
118 register_command(cmd_ctx, NULL, "parport_port", amt_jtagaccel_handle_parport_port_command,
119 COMMAND_CONFIG, NULL);
120 register_command(cmd_ctx, NULL, "rtck", amt_jtagaccel_handle_rtck_command,
121 COMMAND_CONFIG, NULL);
122
123 return ERROR_OK;
124 }
125
126 static void amt_jtagaccel_reset(int trst, int srst)
127 {
128 if (trst == 1)
129 aw_control_rst |= 0x4;
130 else if (trst == 0)
131 aw_control_rst &= ~0x4;
132
133 if (srst == 1)
134 aw_control_rst |= 0x1;
135 else if (srst == 0)
136 aw_control_rst &= ~0x1;
137
138 AMT_AW(aw_control_rst);
139 }
140
141 static int amt_jtagaccel_speed(int speed)
142 {
143 aw_control_baudrate &= 0xf0;
144 aw_control_baudrate |= speed & 0x0f;
145 AMT_AW(aw_control_baudrate);
146
147 return ERROR_OK;
148 }
149
150 static void amt_jtagaccel_end_state(tap_state_t state)
151 {
152 if (tap_is_state_stable(state))
153 tap_set_end_state(state);
154 else
155 {
156 LOG_ERROR("BUG: %i is not a valid end state", state);
157 exit(-1);
158 }
159 }
160
161 static void amt_wait_scan_busy(void)
162 {
163 int timeout = 4096;
164 uint8_t ar_status;
165
166 AMT_AR(ar_status);
167 while (((ar_status) & 0x80) && (timeout-- > 0))
168 AMT_AR(ar_status);
169
170 if (ar_status & 0x80)
171 {
172 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);
173 exit(-1);
174 }
175 }
176
177 static void amt_jtagaccel_state_move(void)
178 {
179 uint8_t aw_scan_tms_5;
180 uint8_t tms_scan[2];
181
182 tap_state_t cur_state = tap_get_state();
183 tap_state_t end_state = tap_get_end_state();
184
185 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][0];
186 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][1];
187
188 aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f);
189 AMT_AW(aw_scan_tms_5);
190 int jtag_speed = jtag_get_speed();
191 if (jtag_speed > 3 || rtck_enabled)
192 amt_wait_scan_busy();
193
194 if (tms_scan[0] & 0x80)
195 {
196 aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
197 AMT_AW(aw_scan_tms_5);
198 if (jtag_speed > 3 || rtck_enabled)
199 amt_wait_scan_busy();
200 }
201
202 tap_set_state(end_state);
203 }
204
205 static void amt_jtagaccel_runtest(int num_cycles)
206 {
207 int i = 0;
208 uint8_t aw_scan_tms_5;
209 uint8_t aw_scan_tms_1to4;
210
211 tap_state_t saved_end_state = tap_get_end_state();
212
213 /* only do a state_move when we're not already in IDLE */
214 if (tap_get_state() != TAP_IDLE)
215 {
216 amt_jtagaccel_end_state(TAP_IDLE);
217 amt_jtagaccel_state_move();
218 }
219
220 while (num_cycles - i >= 5)
221 {
222 aw_scan_tms_5 = 0x40;
223 AMT_AW(aw_scan_tms_5);
224 i += 5;
225 }
226
227 if (num_cycles - i > 0)
228 {
229 aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
230 AMT_AW(aw_scan_tms_1to4);
231 }
232
233 amt_jtagaccel_end_state(saved_end_state);
234 if (tap_get_state() != tap_get_end_state())
235 amt_jtagaccel_state_move();
236 }
237
238 static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
239 {
240 int bits_left = scan_size;
241 int bit_count = 0;
242 tap_state_t saved_end_state = tap_get_end_state();
243 uint8_t aw_tdi_option;
244 uint8_t dw_tdi_scan;
245 uint8_t dr_tdo;
246 uint8_t aw_tms_scan;
247 uint8_t tms_scan[2];
248 int jtag_speed = jtag_get_speed();
249
250 if (ir_scan)
251 amt_jtagaccel_end_state(TAP_IRSHIFT);
252 else
253 amt_jtagaccel_end_state(TAP_DRSHIFT);
254
255 amt_jtagaccel_state_move();
256 amt_jtagaccel_end_state(saved_end_state);
257
258 /* handle unaligned bits at the beginning */
259 if ((scan_size - 1) % 8)
260 {
261 aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
262 AMT_AW(aw_tdi_option);
263
264 dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
265 AMT_DW(dw_tdi_scan);
266 if (jtag_speed > 3 || rtck_enabled)
267 amt_wait_scan_busy();
268
269 if ((type == SCAN_IN) || (type == SCAN_IO))
270 {
271 AMT_DR(dr_tdo);
272 dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
273 buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
274 }
275
276 bit_count += (scan_size - 1) % 8;
277 bits_left -= (scan_size - 1) % 8;
278 }
279
280 while (bits_left - 1 >= 8)
281 {
282 dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
283 AMT_DW(dw_tdi_scan);
284 if (jtag_speed > 3 || rtck_enabled)
285 amt_wait_scan_busy();
286
287 if ((type == SCAN_IN) || (type == SCAN_IO))
288 {
289 AMT_DR(dr_tdo);
290 buf_set_u32(buffer, bit_count, 8, dr_tdo);
291 }
292
293 bit_count += 8;
294 bits_left -= 8;
295 }
296
297 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
298 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
299 aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
300 AMT_AW(aw_tms_scan);
301 if (jtag_speed > 3 || rtck_enabled)
302 amt_wait_scan_busy();
303
304 if ((type == SCAN_IN) || (type == SCAN_IO))
305 {
306 AMT_DR(dr_tdo);
307 dr_tdo = dr_tdo >> 7;
308 buf_set_u32(buffer, bit_count, 1, dr_tdo);
309 }
310
311 if (tms_scan[0] & 0x80)
312 {
313 aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
314 AMT_AW(aw_tms_scan);
315 if (jtag_speed > 3 || rtck_enabled)
316 amt_wait_scan_busy();
317 }
318 tap_set_state(tap_get_end_state());
319 }
320
321 static int amt_jtagaccel_execute_queue(void)
322 {
323 jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
324 int scan_size;
325 enum scan_type type;
326 uint8_t *buffer;
327 int retval;
328
329 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
330 * that wasn't handled by a caller-provided error handler
331 */
332 retval = ERROR_OK;
333
334 while (cmd)
335 {
336 switch (cmd->type)
337 {
338 case JTAG_RESET:
339 #ifdef _DEBUG_JTAG_IO_
340 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
341 #endif
342 if (cmd->cmd.reset->trst == 1)
343 {
344 tap_set_state(TAP_RESET);
345 }
346 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
347 break;
348 case JTAG_RUNTEST:
349 #ifdef _DEBUG_JTAG_IO_
350 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
351 #endif
352 amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
353 amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
354 break;
355 case JTAG_STATEMOVE:
356 #ifdef _DEBUG_JTAG_IO_
357 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
358 #endif
359 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
360 amt_jtagaccel_state_move();
361 break;
362 case JTAG_SCAN:
363 #ifdef _DEBUG_JTAG_IO_
364 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
365 #endif
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 uint8_t control_port;
423 #else
424 uint8_t status_port;
425 #endif
426 uint8_t 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_get_speed());
502
503 enum reset_types jtag_reset_config = jtag_get_reset_config();
504 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
505 aw_control_rst &= ~0x8;
506 else
507 aw_control_rst |= 0x8;
508
509 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
510 aw_control_rst &= ~0x2;
511 else
512 aw_control_rst |= 0x2;
513
514 amt_jtagaccel_reset(0, 0);
515
516 /* read status register */
517 AMT_AR(ar_status);
518 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status);
519
520 return ERROR_OK;
521 }
522
523 static int amt_jtagaccel_quit(void)
524 {
525
526 return ERROR_OK;
527 }
528
529 static int amt_jtagaccel_handle_parport_port_command(
530 struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
531 {
532 if (argc == 1)
533 {
534 /* only if the port wasn't overwritten by cmdline */
535 if (amt_jtagaccel_port == 0)
536 {
537 int retval = parse_u16(args[0], &amt_jtagaccel_port);
538 if (ERROR_OK != retval)
539 return retval;
540 }
541 else
542 {
543 LOG_ERROR("The parport port was already configured!");
544 return ERROR_FAIL;
545 }
546 }
547
548 command_print(cmd_ctx, "parport port = %u", amt_jtagaccel_port);
549
550 return ERROR_OK;
551 }
552
553 static 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)