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

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)