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

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)