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

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)