move jtag drivers to src/jtag/drivers
[openocd.git] / src / jtag / drivers / 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 /* tap_move[i][j]: tap movement command to go from state i to state j
76 * 0: Test-Logic-Reset
77 * 1: Run-Test/Idle
78 * 2: Shift-DR
79 * 3: Pause-DR
80 * 4: Shift-IR
81 * 5: Pause-IR
82 */
83 static uint8_t amt_jtagaccel_tap_move[6][6][2] =
84 {
85 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
86 {{0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00}}, /* RESET */
87 {{0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00}}, /* IDLE */
88 {{0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRSHIFT */
89 {{0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRPAUSE */
90 {{0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00}}, /* IRSHIFT */
91 {{0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00}}, /* IRPAUSE */
92 };
93
94
95 static void amt_jtagaccel_reset(int trst, int srst)
96 {
97 if (trst == 1)
98 aw_control_rst |= 0x4;
99 else if (trst == 0)
100 aw_control_rst &= ~0x4;
101
102 if (srst == 1)
103 aw_control_rst |= 0x1;
104 else if (srst == 0)
105 aw_control_rst &= ~0x1;
106
107 AMT_AW(aw_control_rst);
108 }
109
110 static int amt_jtagaccel_speed(int speed)
111 {
112 aw_control_baudrate &= 0xf0;
113 aw_control_baudrate |= speed & 0x0f;
114 AMT_AW(aw_control_baudrate);
115
116 return ERROR_OK;
117 }
118
119 static void amt_jtagaccel_end_state(tap_state_t state)
120 {
121 if (tap_is_state_stable(state))
122 tap_set_end_state(state);
123 else
124 {
125 LOG_ERROR("BUG: %i is not a valid end state", state);
126 exit(-1);
127 }
128 }
129
130 static void amt_wait_scan_busy(void)
131 {
132 int timeout = 4096;
133 uint8_t ar_status;
134
135 AMT_AR(ar_status);
136 while (((ar_status) & 0x80) && (timeout-- > 0))
137 AMT_AR(ar_status);
138
139 if (ar_status & 0x80)
140 {
141 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);
142 exit(-1);
143 }
144 }
145
146 static void amt_jtagaccel_state_move(void)
147 {
148 uint8_t aw_scan_tms_5;
149 uint8_t tms_scan[2];
150
151 tap_state_t cur_state = tap_get_state();
152 tap_state_t end_state = tap_get_end_state();
153
154 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][0];
155 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][1];
156
157 aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f);
158 AMT_AW(aw_scan_tms_5);
159 int jtag_speed = jtag_get_speed();
160 if (jtag_speed > 3 || rtck_enabled)
161 amt_wait_scan_busy();
162
163 if (tms_scan[0] & 0x80)
164 {
165 aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
166 AMT_AW(aw_scan_tms_5);
167 if (jtag_speed > 3 || rtck_enabled)
168 amt_wait_scan_busy();
169 }
170
171 tap_set_state(end_state);
172 }
173
174 static void amt_jtagaccel_runtest(int num_cycles)
175 {
176 int i = 0;
177 uint8_t aw_scan_tms_5;
178 uint8_t aw_scan_tms_1to4;
179
180 tap_state_t saved_end_state = tap_get_end_state();
181
182 /* only do a state_move when we're not already in IDLE */
183 if (tap_get_state() != TAP_IDLE)
184 {
185 amt_jtagaccel_end_state(TAP_IDLE);
186 amt_jtagaccel_state_move();
187 }
188
189 while (num_cycles - i >= 5)
190 {
191 aw_scan_tms_5 = 0x40;
192 AMT_AW(aw_scan_tms_5);
193 i += 5;
194 }
195
196 if (num_cycles - i > 0)
197 {
198 aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
199 AMT_AW(aw_scan_tms_1to4);
200 }
201
202 amt_jtagaccel_end_state(saved_end_state);
203 if (tap_get_state() != tap_get_end_state())
204 amt_jtagaccel_state_move();
205 }
206
207 static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
208 {
209 int bits_left = scan_size;
210 int bit_count = 0;
211 tap_state_t saved_end_state = tap_get_end_state();
212 uint8_t aw_tdi_option;
213 uint8_t dw_tdi_scan;
214 uint8_t dr_tdo;
215 uint8_t aw_tms_scan;
216 uint8_t tms_scan[2];
217 int jtag_speed = jtag_get_speed();
218
219 if (ir_scan)
220 amt_jtagaccel_end_state(TAP_IRSHIFT);
221 else
222 amt_jtagaccel_end_state(TAP_DRSHIFT);
223
224 amt_jtagaccel_state_move();
225 amt_jtagaccel_end_state(saved_end_state);
226
227 /* handle unaligned bits at the beginning */
228 if ((scan_size - 1) % 8)
229 {
230 aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
231 AMT_AW(aw_tdi_option);
232
233 dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
234 AMT_DW(dw_tdi_scan);
235 if (jtag_speed > 3 || rtck_enabled)
236 amt_wait_scan_busy();
237
238 if ((type == SCAN_IN) || (type == SCAN_IO))
239 {
240 AMT_DR(dr_tdo);
241 dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
242 buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
243 }
244
245 bit_count += (scan_size - 1) % 8;
246 bits_left -= (scan_size - 1) % 8;
247 }
248
249 while (bits_left - 1 >= 8)
250 {
251 dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
252 AMT_DW(dw_tdi_scan);
253 if (jtag_speed > 3 || rtck_enabled)
254 amt_wait_scan_busy();
255
256 if ((type == SCAN_IN) || (type == SCAN_IO))
257 {
258 AMT_DR(dr_tdo);
259 buf_set_u32(buffer, bit_count, 8, dr_tdo);
260 }
261
262 bit_count += 8;
263 bits_left -= 8;
264 }
265
266 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
267 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
268 aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
269 AMT_AW(aw_tms_scan);
270 if (jtag_speed > 3 || rtck_enabled)
271 amt_wait_scan_busy();
272
273 if ((type == SCAN_IN) || (type == SCAN_IO))
274 {
275 AMT_DR(dr_tdo);
276 dr_tdo = dr_tdo >> 7;
277 buf_set_u32(buffer, bit_count, 1, dr_tdo);
278 }
279
280 if (tms_scan[0] & 0x80)
281 {
282 aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
283 AMT_AW(aw_tms_scan);
284 if (jtag_speed > 3 || rtck_enabled)
285 amt_wait_scan_busy();
286 }
287 tap_set_state(tap_get_end_state());
288 }
289
290 static int amt_jtagaccel_execute_queue(void)
291 {
292 struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
293 int scan_size;
294 enum scan_type type;
295 uint8_t *buffer;
296 int retval;
297
298 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
299 * that wasn't handled by a caller-provided error handler
300 */
301 retval = ERROR_OK;
302
303 while (cmd)
304 {
305 switch (cmd->type)
306 {
307 case JTAG_RESET:
308 #ifdef _DEBUG_JTAG_IO_
309 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
310 #endif
311 if (cmd->cmd.reset->trst == 1)
312 {
313 tap_set_state(TAP_RESET);
314 }
315 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
316 break;
317 case JTAG_RUNTEST:
318 #ifdef _DEBUG_JTAG_IO_
319 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
320 #endif
321 amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
322 amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
323 break;
324 case JTAG_STATEMOVE:
325 #ifdef _DEBUG_JTAG_IO_
326 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
327 #endif
328 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
329 amt_jtagaccel_state_move();
330 break;
331 case JTAG_SCAN:
332 #ifdef _DEBUG_JTAG_IO_
333 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
334 #endif
335 amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
336 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
337 type = jtag_scan_type(cmd->cmd.scan);
338 amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
339 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
340 retval = ERROR_JTAG_QUEUE_FAILED;
341 if (buffer)
342 free(buffer);
343 break;
344 case JTAG_SLEEP:
345 #ifdef _DEBUG_JTAG_IO_
346 LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us);
347 #endif
348 jtag_sleep(cmd->cmd.sleep->us);
349 break;
350 default:
351 LOG_ERROR("BUG: unknown JTAG command type encountered");
352 exit(-1);
353 }
354 cmd = cmd->next;
355 }
356
357 return retval;
358 }
359
360 #if PARPORT_USE_GIVEIO == 1
361 int amt_jtagaccel_get_giveio_access(void)
362 {
363 HANDLE h;
364 OSVERSIONINFO version;
365
366 version.dwOSVersionInfoSize = sizeof version;
367 if (!GetVersionEx(&version)) {
368 errno = EINVAL;
369 return -1;
370 }
371 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
372 return 0;
373
374 h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
375 if (h == INVALID_HANDLE_VALUE) {
376 errno = ENODEV;
377 return -1;
378 }
379
380 CloseHandle(h);
381
382 return 0;
383 }
384 #endif
385
386 static int amt_jtagaccel_init(void)
387 {
388 #if PARPORT_USE_PPDEV == 1
389 char buffer[256];
390 int i = 0;
391 uint8_t control_port;
392 #else
393 uint8_t status_port;
394 #endif
395 uint8_t ar_status;
396
397 #if PARPORT_USE_PPDEV == 1
398 if (device_handle > 0)
399 {
400 LOG_ERROR("device is already opened");
401 return ERROR_JTAG_INIT_FAILED;
402 }
403
404 snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
405 device_handle = open(buffer, O_RDWR);
406
407 if (device_handle < 0)
408 {
409 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
410 return ERROR_JTAG_INIT_FAILED;
411 }
412
413 i = ioctl(device_handle, PPCLAIM);
414 if (i < 0)
415 {
416 LOG_ERROR("cannot claim device");
417 return ERROR_JTAG_INIT_FAILED;
418 }
419
420 i = IEEE1284_MODE_EPP;
421 i = ioctl(device_handle, PPSETMODE, & i);
422 if (i < 0)
423 {
424 LOG_ERROR(" cannot set compatible mode to device");
425 return ERROR_JTAG_INIT_FAILED;
426 }
427
428 control_port = 0x00;
429 i = ioctl(device_handle, PPWCONTROL, &control_port);
430
431 control_port = 0x04;
432 i = ioctl(device_handle, PPWCONTROL, &control_port);
433
434 #else
435 if (amt_jtagaccel_port == 0)
436 {
437 amt_jtagaccel_port = 0x378;
438 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
439 }
440
441 #if PARPORT_USE_GIVEIO == 1
442 if (amt_jtagaccel_get_giveio_access() != 0) {
443 #else /* PARPORT_USE_GIVEIO */
444 if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
445 #endif /* PARPORT_USE_GIVEIO */
446 LOG_ERROR("missing privileges for direct i/o");
447 return ERROR_JTAG_INIT_FAILED;
448 }
449
450 /* prepare epp port */
451 /* clear timeout */
452 status_port = inb(amt_jtagaccel_port + 1);
453 outb(status_port | 0x1, amt_jtagaccel_port + 1);
454
455 /* reset epp port */
456 outb(0x00, amt_jtagaccel_port + 2);
457 outb(0x04, amt_jtagaccel_port + 2);
458 #endif
459
460 if (rtck_enabled)
461 {
462 /* set RTCK enable bit */
463 aw_control_fsm |= 0x02;
464 }
465
466 /* enable JTAG port */
467 aw_control_fsm |= 0x04;
468 AMT_AW(aw_control_fsm);
469
470 amt_jtagaccel_speed(jtag_get_speed());
471
472 enum reset_types jtag_reset_config = jtag_get_reset_config();
473 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
474 aw_control_rst &= ~0x8;
475 else
476 aw_control_rst |= 0x8;
477
478 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
479 aw_control_rst &= ~0x2;
480 else
481 aw_control_rst |= 0x2;
482
483 amt_jtagaccel_reset(0, 0);
484
485 /* read status register */
486 AMT_AR(ar_status);
487 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status);
488
489 return ERROR_OK;
490 }
491
492 static int amt_jtagaccel_quit(void)
493 {
494
495 return ERROR_OK;
496 }
497
498 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command)
499 {
500 if (CMD_ARGC == 1)
501 {
502 /* only if the port wasn't overwritten by cmdline */
503 if (amt_jtagaccel_port == 0)
504 {
505 uint16_t port;
506 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
507 amt_jtagaccel_port = port;
508 }
509 else
510 {
511 LOG_ERROR("The parport port was already configured!");
512 return ERROR_FAIL;
513 }
514 }
515
516 command_print(CMD_CTX, "parport port = %u", amt_jtagaccel_port);
517
518 return ERROR_OK;
519 }
520
521 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command)
522 {
523 if (CMD_ARGC == 0)
524 {
525 command_print(CMD_CTX, "amt_jtagaccel RTCK feature %s", (rtck_enabled) ? "enabled" : "disabled");
526 return ERROR_OK;
527 }
528 else
529 {
530 if (strcmp(CMD_ARGV[0], "enabled") == 0)
531 {
532 rtck_enabled = 1;
533 }
534 else
535 {
536 rtck_enabled = 0;
537 }
538 }
539
540 return ERROR_OK;
541 }
542
543 static const struct command_registration amtjtagaccel_command_handlers[] = {
544 {
545 .name = "parport_port",
546 .handler = &amt_jtagaccel_handle_parport_port_command,
547 .mode = COMMAND_CONFIG,
548 .help = "configure the parallel port to use",
549 .usage = "<port_num>",
550 },
551 {
552 .name = "parport_port",
553 .handler = &amt_jtagaccel_handle_rtck_command,
554 .mode = COMMAND_CONFIG,
555 .help = "enable RTCK",
556 .usage = "<enable|disable>",
557 },
558 COMMAND_REGISTRATION_DONE
559 };
560
561 struct jtag_interface amt_jtagaccel_interface = {
562 .name = "amt_jtagaccel",
563 .commands = amtjtagaccel_command_handlers,
564 .init = &amt_jtagaccel_init,
565 .quit = &amt_jtagaccel_quit,
566 .speed = &amt_jtagaccel_speed,
567 .execute_queue = &amt_jtagaccel_execute_queue,
568 };

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)