- fixed arm926 cp15 command bug (thanks to Vincent Palatin for this patch)
[openocd.git] / src / jtag / gw16012.c
1 /***************************************************************************
2 * Copyright (C) 2006 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 #if 1
29 #define _DEBUG_GW16012_IO_
30 #endif
31
32 /* system includes */
33
34 /* system includes */
35 // -ino: 060521-1036
36 #ifdef __FreeBSD__
37
38 #include <sys/types.h>
39 #include <machine/sysarch.h>
40 #include <machine/cpufunc.h>
41 #define ioperm(startport,length,enable)\
42 i386_set_ioperm((startport), (length), (enable))
43
44 #else
45
46 #ifndef _WIN32
47 #include <sys/io.h>
48 #else
49 #include "errno.h"
50 #endif /* _WIN32 */
51
52 #endif /* __FreeBSD__ */
53
54 #include <string.h>
55 #include <stdlib.h>
56
57 #include <sys/time.h>
58 #include <time.h>
59
60 #if PARPORT_USE_PPDEV == 1
61 #ifdef __FreeBSD__
62 #include <dev/ppbus/ppi.h>
63 #include <dev/ppbus/ppbconf.h>
64 #define PPRSTATUS PPIGSTATUS
65 #define PPWDATA PPISDATA
66 #else
67 #include <linux/parport.h>
68 #include <linux/ppdev.h>
69 #endif
70 #include <fcntl.h>
71 #include <sys/ioctl.h>
72 #endif
73
74 #if PARPORT_USE_GIVEIO == 1
75 #if IS_CYGWIN == 1
76 #include <windows.h>
77 #include <errno.h>
78 #undef ERROR
79 #endif
80 #endif
81
82 #include "log.h"
83
84 /* configuration */
85 unsigned long gw16012_port;
86
87 /* interface variables
88 */
89 static u8 gw16012_msb = 0x0;
90 static u8 gw16012_control_value = 0x0;
91
92 #if PARPORT_USE_PPDEV == 1
93 static int device_handle;
94 #endif
95
96 int gw16012_execute_queue(void);
97 int gw16012_register_commands(struct command_context_s *cmd_ctx);
98 int gw16012_speed(int speed);
99 int gw16012_init(void);
100 int gw16012_quit(void);
101
102 int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
103
104 jtag_interface_t gw16012_interface =
105 {
106 .name = "gw16012",
107
108 .execute_queue = gw16012_execute_queue,
109
110 .support_pathmove = 0,
111
112 .speed = gw16012_speed,
113 .register_commands = gw16012_register_commands,
114 .init = gw16012_init,
115 .quit = gw16012_quit,
116 };
117
118 int gw16012_register_commands(struct command_context_s *cmd_ctx)
119 {
120 register_command(cmd_ctx, NULL, "parport_port", gw16012_handle_parport_port_command,
121 COMMAND_CONFIG, NULL);
122
123 return ERROR_OK;
124 }
125
126 void gw16012_data(u8 value)
127 {
128 value = (value & 0x7f) | gw16012_msb;
129 gw16012_msb ^= 0x80; /* toggle MSB */
130
131 #ifdef _DEBUG_GW16012_IO_
132 DEBUG("%2.2x", value);
133 #endif
134
135 #if PARPORT_USE_PPDEV == 1
136 ioctl(device_handle, PPWDATA, &value);
137 #else
138 #ifdef __FreeBSD__
139 outb(gw16012_port, value);
140 #else
141 outb(value, gw16012_port);
142 #endif
143 #endif
144 }
145
146 void gw16012_control(u8 value)
147 {
148 if (value != gw16012_control_value)
149 {
150 gw16012_control_value = value;
151
152 #ifdef _DEBUG_GW16012_IO_
153 DEBUG("%2.2x", gw16012_control_value);
154 #endif
155
156 #if PARPORT_USE_PPDEV == 1
157 ioctl(device_handle, PPWCONTROL, &gw16012_control_value);
158 #else
159 #ifdef __FreeBSD__
160 outb(gw16012_port + 2, gw16012_control_value);
161 #else
162 outb(gw16012_control_value, gw16012_port + 2);
163 #endif
164 #endif
165 }
166 }
167
168 void gw16012_input(u8 *value)
169 {
170 #if PARPORT_USE_PPDEV == 1
171 ioctl(device_handle, PPRSTATUS, value);
172 #else
173 *value = inb(gw16012_port + 1);
174 #endif
175
176 #ifdef _DEBUG_GW16012_IO_
177 DEBUG("%2.2x", *value);
178 #endif
179 }
180
181 /* (1) assert or (0) deassert reset lines */
182 void gw16012_reset(int trst, int srst)
183 {
184 DEBUG("trst: %i, srst: %i", trst, srst);
185
186 if (trst == 0)
187 gw16012_control(0x0d);
188 else if (trst == 1)
189 gw16012_control(0x0c);
190
191 if (srst == 0)
192 gw16012_control(0x0a);
193 else if (srst == 1)
194 gw16012_control(0x0b);
195 }
196
197 int gw16012_speed(int speed)
198 {
199
200 return ERROR_OK;
201 }
202
203 void gw16012_end_state(state)
204 {
205 if (tap_move_map[state] != -1)
206 end_state = state;
207 else
208 {
209 ERROR("BUG: %i is not a valid end state", state);
210 exit(-1);
211 }
212 }
213
214 void gw16012_state_move(void)
215 {
216 int i=0, tms=0;
217 u8 tms_scan = TAP_MOVE(cur_state, end_state);
218
219 gw16012_control(0x0); /* single-bit mode */
220
221 for (i = 0; i < 7; i++)
222 {
223 tms = (tms_scan >> i) & 1;
224 gw16012_data(tms << 1); /* output next TMS bit */
225 }
226
227 cur_state = end_state;
228 }
229
230 void gw16012_path_move(pathmove_command_t *cmd)
231 {
232 int num_states = cmd->num_states;
233 int state_count;
234
235 state_count = 0;
236 while (num_states)
237 {
238 gw16012_control(0x0); /* single-bit mode */
239 if (tap_transitions[cur_state].low == cmd->path[state_count])
240 {
241 gw16012_data(0x0); /* TCK cycle with TMS low */
242 }
243 else if (tap_transitions[cur_state].high == cmd->path[state_count])
244 {
245 gw16012_data(0x2); /* TCK cycle with TMS high */
246 }
247 else
248 {
249 ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);
250 exit(-1);
251 }
252
253 cur_state = cmd->path[state_count];
254 state_count++;
255 num_states--;
256 }
257
258 end_state = cur_state;
259 }
260
261 void gw16012_runtest(int num_cycles)
262 {
263 enum tap_state saved_end_state = end_state;
264 int i;
265
266 /* only do a state_move when we're not already in RTI */
267 if (cur_state != TAP_RTI)
268 {
269 gw16012_end_state(TAP_RTI);
270 gw16012_state_move();
271 }
272
273 for (i = 0; i < num_cycles; i++)
274 {
275 gw16012_control(0x0); /* single-bit mode */
276 gw16012_data(0x0); /* TMS cycle with TMS low */
277 }
278
279 gw16012_end_state(saved_end_state);
280 if (cur_state != end_state)
281 gw16012_state_move();
282 }
283
284 void gw16012_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
285 {
286 int bits_left = scan_size;
287 int bit_count = 0;
288 enum tap_state saved_end_state = end_state;
289 u8 scan_out, scan_in;
290
291 /* only if we're not already in the correct Shift state */
292 if (!((!ir_scan && (cur_state == TAP_SD)) || (ir_scan && (cur_state == TAP_SI))))
293 {
294 if (ir_scan)
295 gw16012_end_state(TAP_SI);
296 else
297 gw16012_end_state(TAP_SD);
298
299 gw16012_state_move();
300 gw16012_end_state(saved_end_state);
301 }
302
303 while (type == SCAN_OUT && ((bits_left - 1) > 7))
304 {
305 gw16012_control(0x2); /* seven-bit mode */
306 scan_out = buf_get_u32(buffer, bit_count, 7);
307 gw16012_data(scan_out);
308 bit_count += 7;
309 bits_left -= 7;
310 }
311
312 gw16012_control(0x0); /* single-bit mode */
313 while (bits_left-- > 0)
314 {
315 u8 tms = 0;
316
317 scan_out = buf_get_u32(buffer, bit_count, 1);
318
319 if (bits_left == 0) /* last bit */
320 {
321 if ((ir_scan && (end_state == TAP_SI))
322 || (!ir_scan && (end_state == TAP_SD)))
323 {
324 tms = 0;
325 }
326 else
327 {
328 tms = 2;
329 }
330 }
331
332 gw16012_data(scan_out | tms);
333
334 if (type != SCAN_OUT)
335 {
336 gw16012_input(&scan_in);
337 buf_set_u32(buffer, bit_count, 1, ((scan_in & 0x08) >> 3));
338 }
339
340 bit_count++;
341 }
342
343 if (!((ir_scan && (end_state == TAP_SI)) ||
344 (!ir_scan && (end_state == TAP_SD))))
345 {
346 gw16012_data(0x0);
347 if (ir_scan)
348 cur_state = TAP_PI;
349 else
350 cur_state = TAP_PD;
351
352 if (cur_state != end_state)
353 gw16012_state_move();
354 }
355 }
356
357 int gw16012_execute_queue(void)
358 {
359 jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
360 int scan_size;
361 enum scan_type type;
362 u8 *buffer;
363
364 while (cmd)
365 {
366 switch (cmd->type)
367 {
368 case JTAG_END_STATE:
369 #ifdef _DEBUG_JTAG_IO_
370 DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
371 #endif
372 if (cmd->cmd.end_state->end_state != -1)
373 gw16012_end_state(cmd->cmd.end_state->end_state);
374 break;
375 case JTAG_RESET:
376 #ifdef _DEBUG_JTAG_IO_
377 DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
378 #endif
379 if (cmd->cmd.reset->trst == 1)
380 {
381 cur_state = TAP_TLR;
382 }
383 gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
384 break;
385 case JTAG_RUNTEST:
386 #ifdef _DEBUG_JTAG_IO_
387 DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
388 #endif
389 if (cmd->cmd.runtest->end_state != -1)
390 gw16012_end_state(cmd->cmd.runtest->end_state);
391 gw16012_runtest(cmd->cmd.runtest->num_cycles);
392 break;
393 case JTAG_STATEMOVE:
394 #ifdef _DEBUG_JTAG_IO_
395 DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
396 #endif
397 if (cmd->cmd.statemove->end_state != -1)
398 gw16012_end_state(cmd->cmd.statemove->end_state);
399 gw16012_state_move();
400 break;
401 case JTAG_PATHMOVE:
402 #ifdef _DEBUG_JTAG_IO_
403 DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
404 #endif
405 gw16012_path_move(cmd->cmd.pathmove);
406 break;
407 case JTAG_SCAN:
408 if (cmd->cmd.scan->end_state != -1)
409 gw16012_end_state(cmd->cmd.scan->end_state);
410 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
411 type = jtag_scan_type(cmd->cmd.scan);
412 #ifdef _DEBUG_JTAG_IO_
413 DEBUG("%s scan (%i) %i bit end in %i", (cmd->cmd.scan->ir_scan) ? "ir" : "dr",
414 type, scan_size, cmd->cmd.scan->end_state);
415 #endif
416 gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
417 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
418 return ERROR_JTAG_QUEUE_FAILED;
419 if (buffer)
420 free(buffer);
421 break;
422 case JTAG_SLEEP:
423 #ifdef _DEBUG_JTAG_IO_
424 DEBUG("sleep %i", cmd->cmd.sleep->us);
425 #endif
426 jtag_sleep(cmd->cmd.sleep->us);
427 break;
428 default:
429 ERROR("BUG: unknown JTAG command type encountered");
430 exit(-1);
431 }
432 cmd = cmd->next;
433 }
434
435 return ERROR_OK;
436 }
437
438 #if PARPORT_USE_GIVEIO == 1
439 int gw16012_get_giveio_access()
440 {
441 HANDLE h;
442 OSVERSIONINFO version;
443
444 version.dwOSVersionInfoSize = sizeof version;
445 if (!GetVersionEx( &version )) {
446 errno = EINVAL;
447 return -1;
448 }
449 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
450 return 0;
451
452 h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
453 if (h == INVALID_HANDLE_VALUE) {
454 errno = ENODEV;
455 return -1;
456 }
457
458 CloseHandle( h );
459
460 return 0;
461 }
462 #endif
463
464 int gw16012_init(void)
465 {
466 #if PARPORT_USE_PPDEV == 1
467 char buffer[256];
468 int i = 0;
469 u8 control_port;
470 #endif
471 u8 status_port;
472
473 #if PARPORT_USE_PPDEV == 1
474 if (device_handle>0)
475 {
476 ERROR("device is already opened");
477 return ERROR_JTAG_INIT_FAILED;
478 }
479
480 #ifdef __FreeBSD__
481 DEBUG("opening /dev/ppi%d...", gw16012_port);
482
483 snprintf(buffer, 256, "/dev/ppi%d", gw16012_port);
484 device_handle = open(buffer, O_WRONLY);
485 #else
486 DEBUG("opening /dev/parport%d...", gw16012_port);
487
488 snprintf(buffer, 256, "/dev/parport%d", gw16012_port);
489 device_handle = open(buffer, O_WRONLY);
490 #endif
491 if (device_handle<0)
492 {
493 ERROR("cannot open device. check it exists and that user read and write rights are set");
494 return ERROR_JTAG_INIT_FAILED;
495 }
496
497 DEBUG("...open");
498
499 #ifndef __FreeBSD__
500 i=ioctl(device_handle, PPCLAIM);
501 if (i<0)
502 {
503 ERROR("cannot claim device");
504 return ERROR_JTAG_INIT_FAILED;
505 }
506
507 i = PARPORT_MODE_COMPAT;
508 i= ioctl(device_handle, PPSETMODE, & i);
509 if (i<0)
510 {
511 ERROR(" cannot set compatible mode to device");
512 return ERROR_JTAG_INIT_FAILED;
513 }
514
515 i = IEEE1284_MODE_COMPAT;
516 i = ioctl(device_handle, PPNEGOT, & i);
517 if (i<0)
518 {
519 ERROR("cannot set compatible 1284 mode to device");
520 return ERROR_JTAG_INIT_FAILED;
521 }
522 #endif
523 #else
524 if (gw16012_port == 0)
525 {
526 gw16012_port = 0x378;
527 WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
528 }
529
530 DEBUG("requesting privileges for parallel port 0x%lx...", gw16012_port);
531 #if PARPORT_USE_GIVEIO == 1
532 if (gw16012_get_giveio_access() != 0)
533 #else /* PARPORT_USE_GIVEIO */
534 if (ioperm(gw16012_port, 3, 1) != 0)
535 #endif /* PARPORT_USE_GIVEIO */
536 {
537 ERROR("missing privileges for direct i/o");
538 return ERROR_JTAG_INIT_FAILED;
539 }
540 DEBUG("...privileges granted");
541
542 /* make sure parallel port is in right mode (clear tristate and interrupt */
543 #ifdef __FreeBSD__
544 outb(gw16012_port + 2, 0x0);
545 #else
546 outb(0x0, gw16012_port + 2);
547 #endif
548 #endif /* PARPORT_USE_PPDEV */
549
550 gw16012_input(&status_port);
551 gw16012_msb = (status_port & 0x80) ^ 0x80;
552
553 gw16012_speed(jtag_speed);
554 gw16012_reset(0, 0);
555
556 return ERROR_OK;
557 }
558
559 int gw16012_quit(void)
560 {
561
562 return ERROR_OK;
563 }
564
565 int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
566 {
567 if (argc == 0)
568 return ERROR_OK;
569
570 /* only if the port wasn't overwritten by cmdline */
571 if (gw16012_port == 0)
572 gw16012_port = strtoul(args[0], NULL, 0);
573
574 return ERROR_OK;
575 }

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)