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

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)