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

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)