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

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)