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

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)