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

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)