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

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)