1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Copyright (C) 2006 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 ***************************************************************************/
12 #include <jtag/interface.h>
13 #include <jtag/commands.h>
16 #define _DEBUG_GW16012_IO_
20 /* -ino: 060521-1036 */
21 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
23 #include <machine/sysarch.h>
24 #include <machine/cpufunc.h>
25 #define ioperm(startport, length, enable) \
26 386_set_ioperm((startport), (length), (enable))
30 #endif /* __FreeBSD__, __FreeBSD_kernel__ */
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
39 #include <linux/parport.h>
40 #include <linux/ppdev.h>
43 #include <sys/ioctl.h>
44 #else /* not PARPORT_USE_PPDEV */
50 #if PARPORT_USE_GIVEIO == 1 && IS_CYGWIN == 1
55 static uint16_t gw16012_port
;
57 /* interface variables
59 static uint8_t gw16012_msb
;
60 static uint8_t gw16012_control_value
;
62 #if PARPORT_USE_PPDEV == 1
63 static int device_handle
;
66 static void gw16012_data(uint8_t value
)
68 value
= (value
& 0x7f) | gw16012_msb
;
69 gw16012_msb
^= 0x80; /* toggle MSB */
71 #ifdef _DEBUG_GW16012_IO_
72 LOG_DEBUG("%2.2x", value
);
75 #if PARPORT_USE_PPDEV == 1
76 ioctl(device_handle
, PPWDATA
, &value
);
78 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
79 outb(gw16012_port
, value
);
81 outb(value
, gw16012_port
);
86 static void gw16012_control(uint8_t value
)
88 if (value
!= gw16012_control_value
) {
89 gw16012_control_value
= value
;
91 #ifdef _DEBUG_GW16012_IO_
92 LOG_DEBUG("%2.2x", gw16012_control_value
);
95 #if PARPORT_USE_PPDEV == 1
96 ioctl(device_handle
, PPWCONTROL
, &gw16012_control_value
);
98 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
99 outb(gw16012_port
+ 2, gw16012_control_value
);
101 outb(gw16012_control_value
, gw16012_port
+ 2);
107 static void gw16012_input(uint8_t *value
)
109 #if PARPORT_USE_PPDEV == 1
110 ioctl(device_handle
, PPRSTATUS
, value
);
112 *value
= inb(gw16012_port
+ 1);
115 #ifdef _DEBUG_GW16012_IO_
116 LOG_DEBUG("%2.2x", *value
);
120 /* (1) assert or (0) deassert reset lines */
121 static void gw16012_reset(int trst
, int srst
)
123 LOG_DEBUG("trst: %i, srst: %i", trst
, srst
);
126 gw16012_control(0x0d);
128 gw16012_control(0x0c);
131 gw16012_control(0x0a);
133 gw16012_control(0x0b);
136 static void gw16012_end_state(tap_state_t state
)
138 if (tap_is_state_stable(state
))
139 tap_set_end_state(state
);
141 LOG_ERROR("BUG: %i is not a valid end state", state
);
146 static void gw16012_state_move(void)
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());
152 gw16012_control(0x0); /* single-bit mode */
154 for (i
= 0; i
< tms_count
; i
++) {
155 tms
= (tms_scan
>> i
) & 1;
156 gw16012_data(tms
<< 1); /* output next TMS bit */
159 tap_set_state(tap_get_end_state());
162 static void gw16012_path_move(struct pathmove_command
*cmd
)
164 int num_states
= cmd
->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 */
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
]));
180 tap_set_state(cmd
->path
[state_count
]);
185 tap_set_end_state(tap_get_state());
188 static void gw16012_runtest(int num_cycles
)
190 tap_state_t saved_end_state
= tap_get_end_state();
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();
199 for (i
= 0; i
< num_cycles
; i
++) {
200 gw16012_control(0x0); /* single-bit mode */
201 gw16012_data(0x0); /* TMS cycle with TMS low */
204 gw16012_end_state(saved_end_state
);
205 if (tap_get_state() != tap_get_end_state())
206 gw16012_state_move();
209 static void gw16012_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
)
211 int bits_left
= scan_size
;
213 tap_state_t saved_end_state
= tap_get_end_state();
214 uint8_t scan_out
, scan_in
;
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
)))) {
220 gw16012_end_state(TAP_IRSHIFT
);
222 gw16012_end_state(TAP_DRSHIFT
);
224 gw16012_state_move();
225 gw16012_end_state(saved_end_state
);
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
);
236 gw16012_control(0x0); /* single-bit mode */
237 while (bits_left
-- > 0) {
240 scan_out
= buf_get_u32(buffer
, bit_count
, 1);
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
)))
250 gw16012_data(scan_out
| tms
);
252 if (type
!= SCAN_OUT
) {
253 gw16012_input(&scan_in
);
254 buf_set_u32(buffer
, bit_count
, 1, ((scan_in
& 0x08) >> 3));
260 if (!((ir_scan
&& (tap_get_end_state() == TAP_IRSHIFT
)) ||
261 (!ir_scan
&& (tap_get_end_state() == TAP_DRSHIFT
)))) {
264 tap_set_state(TAP_IRPAUSE
);
266 tap_set_state(TAP_DRPAUSE
);
268 if (tap_get_state() != tap_get_end_state())
269 gw16012_state_move();
273 static int gw16012_execute_queue(void)
275 struct jtag_command
*cmd
= jtag_command_queue
; /* currently processed command */
281 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
282 * that wasn't handled by a caller-provided error handler
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
);
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
);
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();
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
);
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
;
322 LOG_DEBUG_IO("sleep %" PRIu32
, cmd
->cmd
.sleep
->us
);
323 jtag_sleep(cmd
->cmd
.sleep
->us
);
326 LOG_ERROR("BUG: unknown JTAG command type encountered");
335 #if PARPORT_USE_GIVEIO == 1
336 static int gw16012_get_giveio_access(void)
339 OSVERSIONINFO version
;
341 version
.dwOSVersionInfoSize
= sizeof(version
);
342 if (!GetVersionEx(&version
)) {
346 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
349 h
= CreateFile("\\\\.\\giveio", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
350 FILE_ATTRIBUTE_NORMAL
, NULL
);
351 if (h
== INVALID_HANDLE_VALUE
) {
362 #if PARPORT_USE_PPDEV == 1
364 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
366 #define GW16012_PPDEV_NAME "ppi"
368 static int gw16012_init_ioctls(void)
371 temp
= ioctl(device_handle
, PPCLAIM
);
373 LOG_ERROR("cannot claim device");
374 return ERROR_JTAG_INIT_FAILED
;
377 temp
= PARPORT_MODE_COMPAT
;
378 temp
= ioctl(device_handle
, PPSETMODE
, &temp
);
380 LOG_ERROR(" cannot set compatible mode to device");
381 return ERROR_JTAG_INIT_FAILED
;
384 temp
= IEEE1284_MODE_COMPAT
;
385 temp
= ioctl(device_handle
, PPNEGOT
, &temp
);
387 LOG_ERROR("cannot set compatible 1284 mode to device");
388 return ERROR_JTAG_INIT_FAILED
;
394 #define GW16012_PPDEV_NAME "parport"
396 static int gw16012_init_ioctls(void)
401 #endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
403 static int gw16012_init_device(void)
405 const char *device_name
= GW16012_PPDEV_NAME
;
408 if (device_handle
> 0) {
409 LOG_ERROR("device is already opened");
410 return ERROR_JTAG_INIT_FAILED
;
413 snprintf(buffer
, 256, "/dev/%s%d", device_name
, gw16012_port
);
414 LOG_DEBUG("opening %s...", buffer
);
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
;
422 LOG_DEBUG("...open");
424 if (gw16012_init_ioctls() != ERROR_OK
)
425 return ERROR_JTAG_INIT_FAILED
;
430 #else /* PARPORT_USE_PPDEV */
432 static int gw16012_init_device(void)
434 if (gw16012_port
== 0) {
435 gw16012_port
= 0x378;
436 LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
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
;
448 LOG_DEBUG("...privileges granted");
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);
454 outb(0x0, gw16012_port
+ 2);
459 #endif /* PARPORT_USE_PPDEV */
461 static int gw16012_init(void)
465 if (gw16012_init_device() != ERROR_OK
)
466 return ERROR_JTAG_INIT_FAILED
;
468 gw16012_input(&status_port
);
469 gw16012_msb
= (status_port
& 0x80) ^ 0x80;
476 static int gw16012_quit(void)
482 COMMAND_HANDLER(gw16012_handle_parport_port_command
)
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
);
489 LOG_ERROR("The parport port was already configured!");
494 command_print(CMD
, "parport port = %u", gw16012_port
);
499 static const struct command_registration gw16012_command_handlers
[] = {
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]",
509 COMMAND_REGISTRATION_DONE
512 static struct jtag_interface gw16012_interface
= {
513 .execute_queue
= gw16012_execute_queue
,
516 struct adapter_driver gw16012_adapter_driver
= {
518 .transports
= jtag_only
,
519 .commands
= gw16012_command_handlers
,
521 .init
= gw16012_init
,
522 .quit
= gw16012_quit
,
524 .jtag_ops
= &gw16012_interface
,
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)