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

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)