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

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)