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

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)