dd306f962a7fb956ef5d9544495a5a03447d6cb5
[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 /* -ino: 060521-1036 */
34 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
35
36 #include <sys/types.h>
37 #include <machine/sysarch.h>
38 #include <machine/cpufunc.h>
39 #define ioperm(startport,length,enable)\
40 i386_set_ioperm((startport), (length), (enable))
41
42 #else
43
44 #ifdef _WIN32
45 #include "errno.h"
46 #endif /* _WIN32 */
47
48 #endif /* __FreeBSD__, __FreeBSD_kernel__ */
49
50 #include <string.h>
51 #include <stdlib.h>
52
53 #if PARPORT_USE_PPDEV == 1
54 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
55 #include <dev/ppbus/ppi.h>
56 #include <dev/ppbus/ppbconf.h>
57 #define PPRSTATUS PPIGSTATUS
58 #define PPWDATA PPISDATA
59 #else
60 #include <linux/parport.h>
61 #include <linux/ppdev.h>
62 #endif
63 #include <fcntl.h>
64 #include <sys/ioctl.h>
65 #else /* not PARPORT_USE_PPDEV */
66 #ifndef _WIN32
67 #include <sys/io.h>
68 #endif
69 #endif
70
71 #if PARPORT_USE_GIVEIO == 1
72 #if IS_CYGWIN == 1
73 #include <windows.h>
74 #include <errno.h>
75 #endif
76 #endif
77
78 #include "log.h"
79
80 /* configuration */
81 u16 gw16012_port;
82
83 /* interface variables
84 */
85 static u8 gw16012_msb = 0x0;
86 static u8 gw16012_control_value = 0x0;
87
88 #if PARPORT_USE_PPDEV == 1
89 static int device_handle;
90 #endif
91
92 static int gw16012_execute_queue(void);
93 static int gw16012_register_commands(struct command_context_s *cmd_ctx);
94 static int gw16012_speed(int speed);
95 static int gw16012_init(void);
96 static int gw16012_quit(void);
97
98 static int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
99
100 jtag_interface_t gw16012_interface =
101 {
102 .name = "gw16012",
103
104 .execute_queue = gw16012_execute_queue,
105
106 .speed = gw16012_speed,
107 .register_commands = gw16012_register_commands,
108 .init = gw16012_init,
109 .quit = gw16012_quit,
110 };
111
112 static int gw16012_register_commands(struct command_context_s *cmd_ctx)
113 {
114 register_command(cmd_ctx, NULL, "parport_port", gw16012_handle_parport_port_command,
115 COMMAND_CONFIG, NULL);
116
117 return ERROR_OK;
118 }
119
120 static void gw16012_data(u8 value)
121 {
122 value = (value & 0x7f) | gw16012_msb;
123 gw16012_msb ^= 0x80; /* toggle MSB */
124
125 #ifdef _DEBUG_GW16012_IO_
126 LOG_DEBUG("%2.2x", value);
127 #endif
128
129 #if PARPORT_USE_PPDEV == 1
130 ioctl(device_handle, PPWDATA, &value);
131 #else
132 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
133 outb(gw16012_port, value);
134 #else
135 outb(value, gw16012_port);
136 #endif
137 #endif
138 }
139
140 static void gw16012_control(u8 value)
141 {
142 if (value != gw16012_control_value)
143 {
144 gw16012_control_value = value;
145
146 #ifdef _DEBUG_GW16012_IO_
147 LOG_DEBUG("%2.2x", gw16012_control_value);
148 #endif
149
150 #if PARPORT_USE_PPDEV == 1
151 ioctl(device_handle, PPWCONTROL, &gw16012_control_value);
152 #else
153 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
154 outb(gw16012_port + 2, gw16012_control_value);
155 #else
156 outb(gw16012_control_value, gw16012_port + 2);
157 #endif
158 #endif
159 }
160 }
161
162 static void gw16012_input(u8 *value)
163 {
164 #if PARPORT_USE_PPDEV == 1
165 ioctl(device_handle, PPRSTATUS, value);
166 #else
167 *value = inb(gw16012_port + 1);
168 #endif
169
170 #ifdef _DEBUG_GW16012_IO_
171 LOG_DEBUG("%2.2x", *value);
172 #endif
173 }
174
175 /* (1) assert or (0) deassert reset lines */
176 static void gw16012_reset(int trst, int srst)
177 {
178 LOG_DEBUG("trst: %i, srst: %i", trst, srst);
179
180 if (trst == 0)
181 gw16012_control(0x0d);
182 else if (trst == 1)
183 gw16012_control(0x0c);
184
185 if (srst == 0)
186 gw16012_control(0x0a);
187 else if (srst == 1)
188 gw16012_control(0x0b);
189 }
190
191 static int gw16012_speed(int speed)
192 {
193
194 return ERROR_OK;
195 }
196
197 static void gw16012_end_state(tap_state_t state)
198 {
199 if (tap_is_state_stable(state))
200 tap_set_end_state(state);
201 else
202 {
203 LOG_ERROR("BUG: %i is not a valid end state", state);
204 exit(-1);
205 }
206 }
207
208 static void gw16012_state_move(void)
209 {
210 int i=0, tms=0;
211 u8 tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
212
213 gw16012_control(0x0); /* single-bit mode */
214
215 for (i = 0; i < 7; i++)
216 {
217 tms = (tms_scan >> i) & 1;
218 gw16012_data(tms << 1); /* output next TMS bit */
219 }
220
221 tap_set_state(tap_get_end_state());
222 }
223
224 static void gw16012_path_move(pathmove_command_t *cmd)
225 {
226 int num_states = cmd->num_states;
227 int state_count;
228
229 state_count = 0;
230 while (num_states)
231 {
232 gw16012_control(0x0); /* single-bit mode */
233 if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
234 {
235 gw16012_data(0x0); /* TCK cycle with TMS low */
236 }
237 else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
238 {
239 gw16012_data(0x2); /* TCK cycle with TMS high */
240 }
241 else
242 {
243 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count]));
244 exit(-1);
245 }
246
247 tap_set_state(cmd->path[state_count]);
248 state_count++;
249 num_states--;
250 }
251
252 tap_set_end_state(tap_get_state());
253 }
254
255 static void gw16012_runtest(int num_cycles)
256 {
257 tap_state_t saved_end_state = tap_get_end_state();
258 int i;
259
260 /* only do a state_move when we're not already in IDLE */
261 if (tap_get_state() != TAP_IDLE)
262 {
263 gw16012_end_state(TAP_IDLE);
264 gw16012_state_move();
265 }
266
267 for (i = 0; i < num_cycles; i++)
268 {
269 gw16012_control(0x0); /* single-bit mode */
270 gw16012_data(0x0); /* TMS cycle with TMS low */
271 }
272
273 gw16012_end_state(saved_end_state);
274 if (tap_get_state() != tap_get_end_state())
275 gw16012_state_move();
276 }
277
278 static void gw16012_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
279 {
280 int bits_left = scan_size;
281 int bit_count = 0;
282 tap_state_t saved_end_state = tap_get_end_state();
283 u8 scan_out, scan_in;
284
285 /* only if we're not already in the correct Shift state */
286 if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || (ir_scan && (tap_get_state() == TAP_IRSHIFT))))
287 {
288 if (ir_scan)
289 gw16012_end_state(TAP_IRSHIFT);
290 else
291 gw16012_end_state(TAP_DRSHIFT);
292
293 gw16012_state_move();
294 gw16012_end_state(saved_end_state);
295 }
296
297 while (type == SCAN_OUT && ((bits_left - 1) > 7))
298 {
299 gw16012_control(0x2); /* seven-bit mode */
300 scan_out = buf_get_u32(buffer, bit_count, 7);
301 gw16012_data(scan_out);
302 bit_count += 7;
303 bits_left -= 7;
304 }
305
306 gw16012_control(0x0); /* single-bit mode */
307 while (bits_left-- > 0)
308 {
309 u8 tms = 0;
310
311 scan_out = buf_get_u32(buffer, bit_count, 1);
312
313 if (bits_left == 0) /* last bit */
314 {
315 if ((ir_scan && (tap_get_end_state() == TAP_IRSHIFT))
316 || (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT)))
317 {
318 tms = 0;
319 }
320 else
321 {
322 tms = 2;
323 }
324 }
325
326 gw16012_data(scan_out | tms);
327
328 if (type != SCAN_OUT)
329 {
330 gw16012_input(&scan_in);
331 buf_set_u32(buffer, bit_count, 1, ((scan_in & 0x08) >> 3));
332 }
333
334 bit_count++;
335 }
336
337 if (!((ir_scan && (tap_get_end_state() == TAP_IRSHIFT)) ||
338 (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT))))
339 {
340 gw16012_data(0x0);
341 if (ir_scan)
342 tap_set_state(TAP_IRPAUSE);
343 else
344 tap_set_state(TAP_DRPAUSE);
345
346 if (tap_get_state() != tap_get_end_state())
347 gw16012_state_move();
348 }
349 }
350
351 static int gw16012_execute_queue(void)
352 {
353 jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
354 int scan_size;
355 enum scan_type type;
356 u8 *buffer;
357 int retval;
358
359 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
360 * that wasn't handled by a caller-provided error handler
361 */
362 retval = ERROR_OK;
363
364 while (cmd)
365 {
366 switch (cmd->type)
367 {
368 case JTAG_END_STATE:
369 #ifdef _DEBUG_JTAG_IO_
370 LOG_DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
371 #endif
372 if (cmd->cmd.end_state->end_state != TAP_INVALID)
373 gw16012_end_state(cmd->cmd.end_state->end_state);
374 break;
375 case JTAG_RESET:
376 #ifdef _DEBUG_JTAG_IO_
377 LOG_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 tap_set_state(TAP_RESET);
382 }
383 gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
384 break;
385 case JTAG_RUNTEST:
386 #ifdef _DEBUG_JTAG_IO_
387 LOG_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 != TAP_INVALID)
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 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
396 #endif
397 if (cmd->cmd.statemove->end_state != TAP_INVALID)
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 LOG_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 != TAP_INVALID)
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 LOG_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 retval = ERROR_JTAG_QUEUE_FAILED;
419 if (buffer)
420 free(buffer);
421 break;
422 case JTAG_SLEEP:
423 #ifdef _DEBUG_JTAG_IO_
424 LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
425 #endif
426 jtag_sleep(cmd->cmd.sleep->us);
427 break;
428 default:
429 LOG_ERROR("BUG: unknown JTAG command type encountered");
430 exit(-1);
431 }
432 cmd = cmd->next;
433 }
434
435 return retval;
436 }
437
438 #if PARPORT_USE_GIVEIO == 1
439 static int gw16012_get_giveio_access(void)
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 #if PARPORT_USE_PPDEV == 1
465
466 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
467
468 #define GW16012_PPDEV_NAME "ppi"
469
470 static int gw16012_init_ioctls(void)
471 {
472 int temp = 0;
473 temp = ioctl(device_handle, PPCLAIM);
474 if (temp < 0)
475 {
476 LOG_ERROR("cannot claim device");
477 return ERROR_JTAG_INIT_FAILED;
478 }
479
480 temp = PARPORT_MODE_COMPAT;
481 temp = ioctl(device_handle, PPSETMODE, &temp);
482 if (temp < 0)
483 {
484 LOG_ERROR(" cannot set compatible mode to device");
485 return ERROR_JTAG_INIT_FAILED;
486 }
487
488 temp = IEEE1284_MODE_COMPAT;
489 temp = ioctl(device_handle, PPNEGOT, &temp);
490 if (temp < 0)
491 {
492 LOG_ERROR("cannot set compatible 1284 mode to device");
493 return ERROR_JTAG_INIT_FAILED;
494 }
495 return ERROR_OK;
496 }
497 #else
498
499 #define GW16012_PPDEV_NAME "parport"
500
501 static int gw16012_init_ioctls(void)
502 {
503 return ERROR_OK;
504 }
505
506 #endif // defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
507
508 static int gw16012_init_device(void)
509 {
510 const char *device_name = GW16012_PPDEV_NAME;
511 char buffer[256];
512
513 if (device_handle > 0)
514 {
515 LOG_ERROR("device is already opened");
516 return ERROR_JTAG_INIT_FAILED;
517 }
518
519 snprintf(buffer, 256, "/dev/%s%d", device_name, gw16012_port);
520 LOG_DEBUG("opening %s...", buffer);
521
522 device_handle = open(buffer, O_WRONLY);
523 if (device_handle<0)
524 {
525 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
526 return ERROR_JTAG_INIT_FAILED;
527 }
528
529 LOG_DEBUG("...open");
530
531 if (gw16012_init_ioctls() != ERROR_OK)
532 return ERROR_JTAG_INIT_FAILED;
533
534 return ERROR_OK;
535 }
536
537 #else // PARPORT_USE_PPDEV
538
539 static int gw16012_init_device(void)
540 {
541 if (gw16012_port == 0)
542 {
543 gw16012_port = 0x378;
544 LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
545 }
546
547 LOG_DEBUG("requesting privileges for parallel port 0x%lx...", (long unsigned)(gw16012_port) );
548 #if PARPORT_USE_GIVEIO == 1
549 if (gw16012_get_giveio_access() != 0)
550 #else /* PARPORT_USE_GIVEIO */
551 if (ioperm(gw16012_port, 3, 1) != 0)
552 #endif /* PARPORT_USE_GIVEIO */
553 {
554 LOG_ERROR("missing privileges for direct i/o");
555 return ERROR_JTAG_INIT_FAILED;
556 }
557 LOG_DEBUG("...privileges granted");
558
559 /* make sure parallel port is in right mode (clear tristate and interrupt */
560 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
561 outb(gw16012_port + 2, 0x0);
562 #else
563 outb(0x0, gw16012_port + 2);
564 #endif
565 return ERROR_OK;
566 }
567
568 #endif // PARPORT_USE_PPDEV
569
570 static int gw16012_init(void)
571 {
572 u8 status_port;
573
574 if (gw16012_init_device() != ERROR_OK)
575 return ERROR_JTAG_INIT_FAILED;
576
577 gw16012_input(&status_port);
578 gw16012_msb = (status_port & 0x80) ^ 0x80;
579
580 gw16012_speed(jtag_speed);
581 gw16012_reset(0, 0);
582
583 return ERROR_OK;
584 }
585
586 static int gw16012_quit(void)
587 {
588
589 return ERROR_OK;
590 }
591
592 static int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
593 {
594 if (argc == 0)
595 return ERROR_OK;
596
597 /* only if the port wasn't overwritten by cmdline */
598 if (gw16012_port == 0)
599 gw16012_port = strtoul(args[0], NULL, 0);
600
601 return ERROR_OK;
602 }

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)