- merged XScale branch back into trunk
[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_pathmove = 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, last AR_STATUS: 0x%2.2x", (rtck_enabled) ? "enabled" : "disabled", ar_status);
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 %i", 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 u8 ar_status;
438
439 #if PARPORT_USE_PPDEV == 1
440 if (device_handle > 0)
441 {
442 ERROR("device is already opened");
443 return ERROR_JTAG_INIT_FAILED;
444 }
445
446 snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
447 device_handle = open(buffer, O_RDWR);
448
449 if (device_handle < 0)
450 {
451 ERROR("cannot open device. check it exists and that user read and write rights are set");
452 return ERROR_JTAG_INIT_FAILED;
453 }
454
455 i = ioctl(device_handle, PPCLAIM);
456 if (i < 0)
457 {
458 ERROR("cannot claim device");
459 return ERROR_JTAG_INIT_FAILED;
460 }
461
462 i = IEEE1284_MODE_EPP;
463 i = ioctl(device_handle, PPSETMODE, & i);
464 if (i < 0)
465 {
466 ERROR(" cannot set compatible mode to device");
467 return ERROR_JTAG_INIT_FAILED;
468 }
469
470 control_port = 0x00;
471 i = ioctl(device_handle, PPWCONTROL, &control_port);
472
473 control_port = 0x04;
474 i = ioctl(device_handle, PPWCONTROL, &control_port);
475
476 #else
477 if (amt_jtagaccel_port == 0)
478 {
479 amt_jtagaccel_port = 0x378;
480 WARNING("No parport port specified, using default '0x378' (LPT1)");
481 }
482
483 #if PARPORT_USE_GIVEIO == 1
484 if (amt_jtagaccel_get_giveio_access() != 0) {
485 #else /* PARPORT_USE_GIVEIO */
486 if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
487 #endif /* PARPORT_USE_GIVEIO */
488 ERROR("missing privileges for direct i/o");
489 return ERROR_JTAG_INIT_FAILED;
490 }
491
492 /* prepare epp port */
493 /* clear timeout */
494 status_port = inb(amt_jtagaccel_port + 1);
495 outb(status_port | 0x1, amt_jtagaccel_port + 1);
496
497 /* reset epp port */
498 outb(0x00, amt_jtagaccel_port + 2);
499 outb(0x04, amt_jtagaccel_port + 2);
500 #endif
501
502 if (rtck_enabled)
503 {
504 /* set RTCK enable bit */
505 aw_control_fsm |= 0x02;
506 }
507
508 /* enable JTAG port */
509 aw_control_fsm |= 0x04;
510 AMT_AW(aw_control_fsm);
511
512 amt_jtagaccel_speed(jtag_speed);
513
514 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
515 aw_control_rst &= ~0x8;
516 else
517 aw_control_rst |= 0x8;
518
519 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
520 aw_control_rst &= ~0x2;
521 else
522 aw_control_rst |= 0x2;
523
524 amt_jtagaccel_reset(0, 0);
525
526 /* read status register */
527 AMT_AR(ar_status);
528 DEBUG("AR_STATUS: 0x%2.2x", ar_status);
529
530 return ERROR_OK;
531 }
532
533 int amt_jtagaccel_quit(void)
534 {
535
536 return ERROR_OK;
537 }
538
539 int amt_jtagaccel_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
540 {
541 if (argc == 0)
542 return ERROR_OK;
543
544 /* only if the port wasn't overwritten by cmdline */
545 if (amt_jtagaccel_port == 0)
546 amt_jtagaccel_port = strtoul(args[0], NULL, 0);
547
548 return ERROR_OK;
549 }
550
551 int amt_jtagaccel_handle_rtck_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
552 {
553 if (argc == 0)
554 {
555 command_print(cmd_ctx, "amt_jtagaccel RTCK feature %s", (rtck_enabled) ? "enabled" : "disabled");
556 return ERROR_OK;
557 }
558 else
559 {
560 if (strcmp(args[0], "enabled") == 0)
561 {
562 rtck_enabled = 1;
563 }
564 else
565 {
566 rtck_enabled = 0;
567 }
568 }
569
570 return ERROR_OK;
571 }

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)