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

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)