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

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)