Audit and eliminate redundant #include directives from src/jtag.
[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
201 gw16012_control(0x0); /* single-bit mode */
202
203 for (i = 0; i < 7; i++)
204 {
205 tms = (tms_scan >> i) & 1;
206 gw16012_data(tms << 1); /* output next TMS bit */
207 }
208
209 tap_set_state(tap_get_end_state());
210 }
211
212 static void gw16012_path_move(pathmove_command_t *cmd)
213 {
214 int num_states = cmd->num_states;
215 int state_count;
216
217 state_count = 0;
218 while (num_states)
219 {
220 gw16012_control(0x0); /* single-bit mode */
221 if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
222 {
223 gw16012_data(0x0); /* TCK cycle with TMS low */
224 }
225 else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
226 {
227 gw16012_data(0x2); /* TCK cycle with TMS high */
228 }
229 else
230 {
231 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count]));
232 exit(-1);
233 }
234
235 tap_set_state(cmd->path[state_count]);
236 state_count++;
237 num_states--;
238 }
239
240 tap_set_end_state(tap_get_state());
241 }
242
243 static void gw16012_runtest(int num_cycles)
244 {
245 tap_state_t saved_end_state = tap_get_end_state();
246 int i;
247
248 /* only do a state_move when we're not already in IDLE */
249 if (tap_get_state() != TAP_IDLE)
250 {
251 gw16012_end_state(TAP_IDLE);
252 gw16012_state_move();
253 }
254
255 for (i = 0; i < num_cycles; i++)
256 {
257 gw16012_control(0x0); /* single-bit mode */
258 gw16012_data(0x0); /* TMS cycle with TMS low */
259 }
260
261 gw16012_end_state(saved_end_state);
262 if (tap_get_state() != tap_get_end_state())
263 gw16012_state_move();
264 }
265
266 static void gw16012_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
267 {
268 int bits_left = scan_size;
269 int bit_count = 0;
270 tap_state_t saved_end_state = tap_get_end_state();
271 u8 scan_out, scan_in;
272
273 /* only if we're not already in the correct Shift state */
274 if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || (ir_scan && (tap_get_state() == TAP_IRSHIFT))))
275 {
276 if (ir_scan)
277 gw16012_end_state(TAP_IRSHIFT);
278 else
279 gw16012_end_state(TAP_DRSHIFT);
280
281 gw16012_state_move();
282 gw16012_end_state(saved_end_state);
283 }
284
285 while (type == SCAN_OUT && ((bits_left - 1) > 7))
286 {
287 gw16012_control(0x2); /* seven-bit mode */
288 scan_out = buf_get_u32(buffer, bit_count, 7);
289 gw16012_data(scan_out);
290 bit_count += 7;
291 bits_left -= 7;
292 }
293
294 gw16012_control(0x0); /* single-bit mode */
295 while (bits_left-- > 0)
296 {
297 u8 tms = 0;
298
299 scan_out = buf_get_u32(buffer, bit_count, 1);
300
301 if (bits_left == 0) /* last bit */
302 {
303 if ((ir_scan && (tap_get_end_state() == TAP_IRSHIFT))
304 || (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT)))
305 {
306 tms = 0;
307 }
308 else
309 {
310 tms = 2;
311 }
312 }
313
314 gw16012_data(scan_out | tms);
315
316 if (type != SCAN_OUT)
317 {
318 gw16012_input(&scan_in);
319 buf_set_u32(buffer, bit_count, 1, ((scan_in & 0x08) >> 3));
320 }
321
322 bit_count++;
323 }
324
325 if (!((ir_scan && (tap_get_end_state() == TAP_IRSHIFT)) ||
326 (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT))))
327 {
328 gw16012_data(0x0);
329 if (ir_scan)
330 tap_set_state(TAP_IRPAUSE);
331 else
332 tap_set_state(TAP_DRPAUSE);
333
334 if (tap_get_state() != tap_get_end_state())
335 gw16012_state_move();
336 }
337 }
338
339 static int gw16012_execute_queue(void)
340 {
341 jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
342 int scan_size;
343 enum scan_type type;
344 u8 *buffer;
345 int retval;
346
347 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
348 * that wasn't handled by a caller-provided error handler
349 */
350 retval = ERROR_OK;
351
352 while (cmd)
353 {
354 switch (cmd->type)
355 {
356 case JTAG_END_STATE:
357 #ifdef _DEBUG_JTAG_IO_
358 LOG_DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
359 #endif
360 if (cmd->cmd.end_state->end_state != TAP_INVALID)
361 gw16012_end_state(cmd->cmd.end_state->end_state);
362 break;
363 case JTAG_RESET:
364 #ifdef _DEBUG_JTAG_IO_
365 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
366 #endif
367 if (cmd->cmd.reset->trst == 1)
368 {
369 tap_set_state(TAP_RESET);
370 }
371 gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
372 break;
373 case JTAG_RUNTEST:
374 #ifdef _DEBUG_JTAG_IO_
375 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
376 #endif
377 if (cmd->cmd.runtest->end_state != TAP_INVALID)
378 gw16012_end_state(cmd->cmd.runtest->end_state);
379 gw16012_runtest(cmd->cmd.runtest->num_cycles);
380 break;
381 case JTAG_STATEMOVE:
382 #ifdef _DEBUG_JTAG_IO_
383 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
384 #endif
385 if (cmd->cmd.statemove->end_state != TAP_INVALID)
386 gw16012_end_state(cmd->cmd.statemove->end_state);
387 gw16012_state_move();
388 break;
389 case JTAG_PATHMOVE:
390 #ifdef _DEBUG_JTAG_IO_
391 LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
392 #endif
393 gw16012_path_move(cmd->cmd.pathmove);
394 break;
395 case JTAG_SCAN:
396 if (cmd->cmd.scan->end_state != TAP_INVALID)
397 gw16012_end_state(cmd->cmd.scan->end_state);
398 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
399 type = jtag_scan_type(cmd->cmd.scan);
400 #ifdef _DEBUG_JTAG_IO_
401 LOG_DEBUG("%s scan (%i) %i bit end in %i", (cmd->cmd.scan->ir_scan) ? "ir" : "dr",
402 type, scan_size, cmd->cmd.scan->end_state);
403 #endif
404 gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
405 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
406 retval = ERROR_JTAG_QUEUE_FAILED;
407 if (buffer)
408 free(buffer);
409 break;
410 case JTAG_SLEEP:
411 #ifdef _DEBUG_JTAG_IO_
412 LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
413 #endif
414 jtag_sleep(cmd->cmd.sleep->us);
415 break;
416 default:
417 LOG_ERROR("BUG: unknown JTAG command type encountered");
418 exit(-1);
419 }
420 cmd = cmd->next;
421 }
422
423 return retval;
424 }
425
426 #if PARPORT_USE_GIVEIO == 1
427 static int gw16012_get_giveio_access(void)
428 {
429 HANDLE h;
430 OSVERSIONINFO version;
431
432 version.dwOSVersionInfoSize = sizeof version;
433 if (!GetVersionEx( &version )) {
434 errno = EINVAL;
435 return -1;
436 }
437 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
438 return 0;
439
440 h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
441 if (h == INVALID_HANDLE_VALUE) {
442 errno = ENODEV;
443 return -1;
444 }
445
446 CloseHandle( h );
447
448 return 0;
449 }
450 #endif
451
452 #if PARPORT_USE_PPDEV == 1
453
454 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
455
456 #define GW16012_PPDEV_NAME "ppi"
457
458 static int gw16012_init_ioctls(void)
459 {
460 int temp = 0;
461 temp = ioctl(device_handle, PPCLAIM);
462 if (temp < 0)
463 {
464 LOG_ERROR("cannot claim device");
465 return ERROR_JTAG_INIT_FAILED;
466 }
467
468 temp = PARPORT_MODE_COMPAT;
469 temp = ioctl(device_handle, PPSETMODE, &temp);
470 if (temp < 0)
471 {
472 LOG_ERROR(" cannot set compatible mode to device");
473 return ERROR_JTAG_INIT_FAILED;
474 }
475
476 temp = IEEE1284_MODE_COMPAT;
477 temp = ioctl(device_handle, PPNEGOT, &temp);
478 if (temp < 0)
479 {
480 LOG_ERROR("cannot set compatible 1284 mode to device");
481 return ERROR_JTAG_INIT_FAILED;
482 }
483 return ERROR_OK;
484 }
485 #else
486
487 #define GW16012_PPDEV_NAME "parport"
488
489 static int gw16012_init_ioctls(void)
490 {
491 return ERROR_OK;
492 }
493
494 #endif // defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
495
496 static int gw16012_init_device(void)
497 {
498 const char *device_name = GW16012_PPDEV_NAME;
499 char buffer[256];
500
501 if (device_handle > 0)
502 {
503 LOG_ERROR("device is already opened");
504 return ERROR_JTAG_INIT_FAILED;
505 }
506
507 snprintf(buffer, 256, "/dev/%s%d", device_name, gw16012_port);
508 LOG_DEBUG("opening %s...", buffer);
509
510 device_handle = open(buffer, O_WRONLY);
511 if (device_handle<0)
512 {
513 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
514 return ERROR_JTAG_INIT_FAILED;
515 }
516
517 LOG_DEBUG("...open");
518
519 if (gw16012_init_ioctls() != ERROR_OK)
520 return ERROR_JTAG_INIT_FAILED;
521
522 return ERROR_OK;
523 }
524
525 #else // PARPORT_USE_PPDEV
526
527 static int gw16012_init_device(void)
528 {
529 if (gw16012_port == 0)
530 {
531 gw16012_port = 0x378;
532 LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
533 }
534
535 LOG_DEBUG("requesting privileges for parallel port 0x%lx...", (long unsigned)(gw16012_port) );
536 #if PARPORT_USE_GIVEIO == 1
537 if (gw16012_get_giveio_access() != 0)
538 #else /* PARPORT_USE_GIVEIO */
539 if (ioperm(gw16012_port, 3, 1) != 0)
540 #endif /* PARPORT_USE_GIVEIO */
541 {
542 LOG_ERROR("missing privileges for direct i/o");
543 return ERROR_JTAG_INIT_FAILED;
544 }
545 LOG_DEBUG("...privileges granted");
546
547 /* make sure parallel port is in right mode (clear tristate and interrupt */
548 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
549 outb(gw16012_port + 2, 0x0);
550 #else
551 outb(0x0, gw16012_port + 2);
552 #endif
553 return ERROR_OK;
554 }
555
556 #endif // PARPORT_USE_PPDEV
557
558 static int gw16012_init(void)
559 {
560 u8 status_port;
561
562 if (gw16012_init_device() != ERROR_OK)
563 return ERROR_JTAG_INIT_FAILED;
564
565 gw16012_input(&status_port);
566 gw16012_msb = (status_port & 0x80) ^ 0x80;
567
568 gw16012_speed(jtag_speed);
569 gw16012_reset(0, 0);
570
571 return ERROR_OK;
572 }
573
574 static int gw16012_quit(void)
575 {
576
577 return ERROR_OK;
578 }
579
580 static int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
581 {
582 if (argc == 0)
583 return ERROR_OK;
584
585 /* only if the port wasn't overwritten by cmdline */
586 if (gw16012_port == 0)
587 gw16012_port = strtoul(args[0], NULL, 0);
588
589 return ERROR_OK;
590 }

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)