- allow building for MinGW using either -mno-cygwin or the MinGW gcc
[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 "replacements.h"
25
26 #include "jtag.h"
27
28 /* system includes */
29
30 #ifndef _WIN32
31 #include <sys/io.h>
32 #else
33 #include "errno.h"
34 #endif /* _WIN32 */
35
36 #include <string.h>
37 #include <stdlib.h>
38
39 #include <sys/time.h>
40 #include <time.h>
41
42 #if PARPORT_USE_PPDEV == 1
43 #include <linux/parport.h>
44 #include <linux/ppdev.h>
45 #include <fcntl.h>
46 #include <sys/ioctl.h>
47 #include <unistd.h>
48 #endif
49
50 #if PARPORT_USE_GIVEIO == 1
51 #if IS_CYGWIN == 1
52 #include <windows.h>
53 #include <errno.h>
54 #undef ERROR
55 #endif
56 #endif
57
58 #include "log.h"
59
60 /* configuration */
61 unsigned long amt_jtagaccel_port;
62
63 /* interface variables
64 */
65 static u8 aw_control_rst = 0x00;
66 static u8 aw_control_fsm = 0x10;
67 static u8 aw_control_baudrate = 0x20;
68
69 static int rtck_enabled = 0;
70
71 #if PARPORT_USE_PPDEV == 1
72 static int device_handle;
73 int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR ;
74 int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA ;
75 #define AMT_AW(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); write(device_handle, &val, 1); } while (0)
76 #define AMT_AR(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); read(device_handle, &val, 1); } while (0)
77 #define AMT_DW(val) do { ioctl(device_handle, PPSETMODE, &data_mode); write(device_handle, &val, 1); } while (0)
78 #define AMT_DR(val) do { ioctl(device_handle, PPSETMODE, &data_mode); read(device_handle, &val, 1); } while (0)
79 #else
80 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
81 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
82 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
83 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
84 #endif
85
86 int amt_jtagaccel_execute_queue(void);
87 int amt_jtagaccel_register_commands(struct command_context_s *cmd_ctx);
88 int amt_jtagaccel_speed(int speed);
89 int amt_jtagaccel_init(void);
90 int amt_jtagaccel_quit(void);
91
92 int amt_jtagaccel_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
93 int amt_jtagaccel_handle_rtck_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
94
95 /* tap_move[i][j]: tap movement command to go from state i to state j
96 * 0: Test-Logic-Reset
97 * 1: Run-Test/Idle
98 * 2: Shift-DR
99 * 3: Pause-DR
100 * 4: Shift-IR
101 * 5: Pause-IR
102 */
103 u8 amt_jtagaccel_tap_move[6][6][2] =
104 {
105 /* TLR RTI SD PD SI PI */
106 {{0x1f, 0x00}, {0x0f, 0x00}, {0x8a, 0x04}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00}}, /* TLR */
107 {{0x1f, 0x00}, {0x00, 0x00}, {0x85, 0x08}, {0x05, 0x00}, {0x8b, 0x08}, {0x0b, 0x00}}, /* RTI */
108 {{0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* SD */
109 {{0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* PD */
110 {{0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00}}, /* SI */
111 {{0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00}}, /* PI */
112 };
113
114 jtag_interface_t amt_jtagaccel_interface =
115 {
116 .name = "amt_jtagaccel",
117
118 .execute_queue = amt_jtagaccel_execute_queue,
119
120 .support_statemove = 0,
121
122 .speed = amt_jtagaccel_speed,
123 .register_commands = amt_jtagaccel_register_commands,
124 .init = amt_jtagaccel_init,
125 .quit = amt_jtagaccel_quit,
126 };
127
128 int amt_jtagaccel_register_commands(struct command_context_s *cmd_ctx)
129 {
130 register_command(cmd_ctx, NULL, "parport_port", amt_jtagaccel_handle_parport_port_command,
131 COMMAND_CONFIG, NULL);
132 register_command(cmd_ctx, NULL, "rtck", amt_jtagaccel_handle_rtck_command,
133 COMMAND_CONFIG, NULL);
134
135 return ERROR_OK;
136 }
137
138 void amt_jtagaccel_reset(int trst, int srst)
139 {
140 if (trst == 1)
141 aw_control_rst |= 0x4;
142 else if (trst == 0)
143 aw_control_rst &= ~0x4;
144
145 if (srst == 1)
146 aw_control_rst |= 0x1;
147 else if (srst == 0)
148 aw_control_rst &= ~0x1;
149
150 AMT_AW(aw_control_rst);
151 }
152
153 int amt_jtagaccel_speed(int speed)
154 {
155 aw_control_baudrate &= 0xf0;
156 aw_control_baudrate |= speed & 0x0f;
157 AMT_AW(aw_control_baudrate);
158
159 return ERROR_OK;
160 }
161
162 void amt_jtagaccel_end_state(state)
163 {
164 if (tap_move_map[state] != -1)
165 end_state = state;
166 else
167 {
168 ERROR("BUG: %i is not a valid end state", state);
169 exit(-1);
170 }
171 }
172
173 void amt_wait_scan_busy()
174 {
175 int timeout = 4096;
176 u8 ar_status;
177
178 AMT_AR(ar_status);
179 while (((ar_status) & 0x80) && (timeout-- > 0))
180 AMT_AR(ar_status);
181
182 if (ar_status & 0x80)
183 {
184 ERROR("amt_jtagaccel timed out while waiting for end of scan, rtck was %s", (rtck_enabled) ? "enabled" : "disabled");
185 exit(-1);
186 }
187 }
188
189 void amt_jtagaccel_state_move(void)
190 {
191 u8 aw_scan_tms_5;
192 u8 tms_scan[2];
193
194 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][0];
195 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][1];
196
197 aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f);
198 AMT_AW(aw_scan_tms_5);
199 if (jtag_speed > 3 || rtck_enabled)
200 amt_wait_scan_busy();
201
202 if (tms_scan[0] & 0x80)
203 {
204 aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
205 AMT_AW(aw_scan_tms_5);
206 if (jtag_speed > 3 || rtck_enabled)
207 amt_wait_scan_busy();
208 }
209
210 cur_state = end_state;
211 }
212
213 void amt_jtagaccel_runtest(int num_cycles)
214 {
215 int i = 0;
216 u8 aw_scan_tms_5;
217 u8 aw_scan_tms_1to4;
218
219 enum tap_state saved_end_state = end_state;
220
221 /* only do a state_move when we're not already in RTI */
222 if (cur_state != TAP_RTI)
223 {
224 amt_jtagaccel_end_state(TAP_RTI);
225 amt_jtagaccel_state_move();
226 }
227
228 while (num_cycles - i >= 5)
229 {
230 aw_scan_tms_5 = 0x40;
231 AMT_AW(aw_scan_tms_5);
232 i += 5;
233 }
234
235 if (num_cycles - i > 0)
236 {
237 aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
238 AMT_AW(aw_scan_tms_1to4);
239 }
240
241 amt_jtagaccel_end_state(saved_end_state);
242 if (cur_state != end_state)
243 amt_jtagaccel_state_move();
244 }
245
246 void amt_jtagaccel_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
247 {
248 int bits_left = scan_size;
249 int bit_count = 0;
250 enum tap_state saved_end_state = end_state;
251 u8 aw_tdi_option;
252 u8 dw_tdi_scan;
253 u8 dr_tdo;
254 u8 aw_tms_scan;
255 u8 tms_scan[2];
256
257 if (ir_scan)
258 amt_jtagaccel_end_state(TAP_SI);
259 else
260 amt_jtagaccel_end_state(TAP_SD);
261
262 amt_jtagaccel_state_move();
263 amt_jtagaccel_end_state(saved_end_state);
264
265 /* handle unaligned bits at the beginning */
266 if ((scan_size - 1) % 8)
267 {
268 aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
269 AMT_AW(aw_tdi_option);
270
271 dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
272 AMT_DW(dw_tdi_scan);
273 if (jtag_speed > 3 || rtck_enabled)
274 amt_wait_scan_busy();
275
276 if ((type == SCAN_IN) || (type == SCAN_IO))
277 {
278 AMT_DR(dr_tdo);
279 dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
280 buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
281 }
282
283 bit_count += (scan_size - 1) % 8;
284 bits_left -= (scan_size - 1) % 8;
285 }
286
287 while (bits_left - 1 >= 8)
288 {
289 dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
290 AMT_DW(dw_tdi_scan);
291 if (jtag_speed > 3 || rtck_enabled)
292 amt_wait_scan_busy();
293
294 if ((type == SCAN_IN) || (type == SCAN_IO))
295 {
296 AMT_DR(dr_tdo);
297 buf_set_u32(buffer, bit_count, 8, dr_tdo);
298 }
299
300 bit_count += 8;
301 bits_left -= 8;
302 }
303
304 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][0];
305 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][1];
306 aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
307 AMT_AW(aw_tms_scan);
308 if (jtag_speed > 3 || rtck_enabled)
309 amt_wait_scan_busy();
310
311 if ((type == SCAN_IN) || (type == SCAN_IO))
312 {
313 AMT_DR(dr_tdo);
314 dr_tdo = dr_tdo >> 7;
315 buf_set_u32(buffer, bit_count, 1, dr_tdo);
316 }
317
318 if (tms_scan[0] & 0x80)
319 {
320 aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
321 AMT_AW(aw_tms_scan);
322 if (jtag_speed > 3 || rtck_enabled)
323 amt_wait_scan_busy();
324 }
325 cur_state = end_state;
326 }
327
328 int amt_jtagaccel_execute_queue(void)
329 {
330 jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
331 int scan_size;
332 enum scan_type type;
333 u8 *buffer;
334
335 while (cmd)
336 {
337 switch (cmd->type)
338 {
339 case JTAG_END_STATE:
340 #ifdef _DEBUG_JTAG_IO_
341 DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
342 #endif
343 if (cmd->cmd.end_state->end_state != -1)
344 amt_jtagaccel_end_state(cmd->cmd.end_state->end_state);
345 break;
346 case JTAG_RESET:
347 #ifdef _DEBUG_JTAG_IO_
348 DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
349 #endif
350 if (cmd->cmd.reset->trst == 1)
351 {
352 cur_state = TAP_TLR;
353 }
354 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
355 break;
356 case JTAG_RUNTEST:
357 #ifdef _DEBUG_JTAG_IO_
358 DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
359 #endif
360 if (cmd->cmd.runtest->end_state != -1)
361 amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
362 amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
363 break;
364 case JTAG_STATEMOVE:
365 #ifdef _DEBUG_JTAG_IO_
366 DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
367 #endif
368 if (cmd->cmd.statemove->end_state != -1)
369 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
370 amt_jtagaccel_state_move();
371 break;
372 case JTAG_SCAN:
373 #ifdef _DEBUG_JTAG_IO_
374 DEBUG("scan end in %i", cmd->cmd.scan->end_state);
375 #endif
376 if (cmd->cmd.scan->end_state != -1)
377 amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
378 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
379 type = jtag_scan_type(cmd->cmd.scan);
380 amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
381 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
382 return ERROR_JTAG_QUEUE_FAILED;
383 if (buffer)
384 free(buffer);
385 break;
386 case JTAG_SLEEP:
387 #ifdef _DEBUG_JTAG_IO_
388 DEBUG("sleep", cmd->cmd.sleep->us);
389 #endif
390 jtag_sleep(cmd->cmd.sleep->us);
391 break;
392 default:
393 ERROR("BUG: unknown JTAG command type encountered");
394 exit(-1);
395 }
396 cmd = cmd->next;
397 }
398
399 return ERROR_OK;
400 }
401
402 #if PARPORT_USE_GIVEIO == 1
403 int amt_jtagaccel_get_giveio_access()
404 {
405 HANDLE h;
406 OSVERSIONINFO version;
407
408 version.dwOSVersionInfoSize = sizeof version;
409 if (!GetVersionEx( &version )) {
410 errno = EINVAL;
411 return -1;
412 }
413 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
414 return 0;
415
416 h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
417 if (h == INVALID_HANDLE_VALUE) {
418 errno = ENODEV;
419 return -1;
420 }
421
422 CloseHandle( h );
423
424 return 0;
425 }
426 #endif
427
428 int amt_jtagaccel_init(void)
429 {
430 #if PARPORT_USE_PPDEV == 1
431 char buffer[256];
432 int i = 0;
433 u8 control_port;
434 #else
435 u8 status_port;
436 #endif
437
438 #if PARPORT_USE_PPDEV == 1
439 if (device_handle > 0)
440 {
441 ERROR("device is already opened");
442 return ERROR_JTAG_INIT_FAILED;
443 }
444
445 snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
446 device_handle = open(buffer, O_RDWR);
447
448 if (device_handle < 0)
449 {
450 ERROR("cannot open device. check it exists and that user read and write rights are set");
451 return ERROR_JTAG_INIT_FAILED;
452 }
453
454 i = ioctl(device_handle, PPCLAIM);
455 if (i < 0)
456 {
457 ERROR("cannot claim device");
458 return ERROR_JTAG_INIT_FAILED;
459 }
460
461 i = IEEE1284_MODE_EPP;
462 i = ioctl(device_handle, PPSETMODE, & i);
463 if (i < 0)
464 {
465 ERROR(" cannot set compatible mode to device");
466 return ERROR_JTAG_INIT_FAILED;
467 }
468
469 control_port = 0x00;
470 i = ioctl(device_handle, PPWCONTROL, &control_port);
471
472 control_port = 0x04;
473 i = ioctl(device_handle, PPWCONTROL, &control_port);
474
475 #else
476 if (amt_jtagaccel_port == 0)
477 {
478 amt_jtagaccel_port = 0x378;
479 WARNING("No parport port specified, using default '0x378' (LPT1)");
480 }
481
482 #if PARPORT_USE_GIVEIO == 1
483 if (amt_jtagaccel_get_giveio_access() != 0) {
484 #else /* PARPORT_USE_GIVEIO */
485 if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
486 #endif /* PARPORT_USE_GIVEIO */
487 ERROR("missing privileges for direct i/o");
488 return ERROR_JTAG_INIT_FAILED;
489 }
490
491 /* prepare epp port */
492 /* clear timeout */
493 status_port = inb(amt_jtagaccel_port + 1);
494 outb(status_port | 0x1, amt_jtagaccel_port + 1);
495
496 /* reset epp port */
497 outb(0x00, amt_jtagaccel_port + 2);
498 outb(0x04, amt_jtagaccel_port + 2);
499 #endif
500
501 /* enable JTAG port */
502 aw_control_fsm |= 0x04;
503 AMT_AW(aw_control_fsm);
504
505 amt_jtagaccel_speed(jtag_speed);
506
507 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
508 aw_control_rst &= ~0x8;
509 else
510 aw_control_rst |= 0x8;
511
512 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
513 aw_control_rst &= ~0x2;
514 else
515 aw_control_rst |= 0x2;
516
517 amt_jtagaccel_reset(0, 0);
518
519 return ERROR_OK;
520 }
521
522 int amt_jtagaccel_quit(void)
523 {
524
525 return ERROR_OK;
526 }
527
528 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 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 /* set RTCK enable bit */
554 aw_control_fsm |= 0x02;
555 AMT_AW(aw_control_fsm);
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)