1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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. *
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. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
23 #include <jtag/interface.h>
24 #include <jtag/commands.h>
27 #define _DEBUG_GW16012_IO_
31 /* -ino: 060521-1036 */
32 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
34 #include <machine/sysarch.h>
35 #include <machine/cpufunc.h>
36 #define ioperm(startport, length, enable) \
37 386_set_ioperm((startport), (length), (enable))
41 #endif /* __FreeBSD__, __FreeBSD_kernel__ */
43 #if PARPORT_USE_PPDEV == 1
44 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
45 #include <dev/ppbus/ppi.h>
46 #include <dev/ppbus/ppbconf.h>
47 #define PPRSTATUS PPIGSTATUS
48 #define PPWDATA PPISDATA
50 #include <linux/parport.h>
51 #include <linux/ppdev.h>
54 #include <sys/ioctl.h>
55 #else /* not PARPORT_USE_PPDEV */
61 #if PARPORT_USE_GIVEIO == 1 && IS_CYGWIN == 1
66 static uint16_t gw16012_port
;
68 /* interface variables
70 static uint8_t gw16012_msb
;
71 static uint8_t gw16012_control_value
;
73 #if PARPORT_USE_PPDEV == 1
74 static int device_handle
;
77 static void gw16012_data(uint8_t value
)
79 value
= (value
& 0x7f) | gw16012_msb
;
80 gw16012_msb
^= 0x80; /* toggle MSB */
82 #ifdef _DEBUG_GW16012_IO_
83 LOG_DEBUG("%2.2x", value
);
86 #if PARPORT_USE_PPDEV == 1
87 ioctl(device_handle
, PPWDATA
, &value
);
89 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
90 outb(gw16012_port
, value
);
92 outb(value
, gw16012_port
);
97 static void gw16012_control(uint8_t value
)
99 if (value
!= gw16012_control_value
) {
100 gw16012_control_value
= value
;
102 #ifdef _DEBUG_GW16012_IO_
103 LOG_DEBUG("%2.2x", gw16012_control_value
);
106 #if PARPORT_USE_PPDEV == 1
107 ioctl(device_handle
, PPWCONTROL
, &gw16012_control_value
);
109 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
110 outb(gw16012_port
+ 2, gw16012_control_value
);
112 outb(gw16012_control_value
, gw16012_port
+ 2);
118 static void gw16012_input(uint8_t *value
)
120 #if PARPORT_USE_PPDEV == 1
121 ioctl(device_handle
, PPRSTATUS
, value
);
123 *value
= inb(gw16012_port
+ 1);
126 #ifdef _DEBUG_GW16012_IO_
127 LOG_DEBUG("%2.2x", *value
);
131 /* (1) assert or (0) deassert reset lines */
132 static void gw16012_reset(int trst
, int srst
)
134 LOG_DEBUG("trst: %i, srst: %i", trst
, srst
);
137 gw16012_control(0x0d);
139 gw16012_control(0x0c);
142 gw16012_control(0x0a);
144 gw16012_control(0x0b);
147 static void gw16012_end_state(tap_state_t state
)
149 if (tap_is_state_stable(state
))
150 tap_set_end_state(state
);
152 LOG_ERROR("BUG: %i is not a valid end state", state
);
157 static void gw16012_state_move(void)
160 uint8_t tms_scan
= tap_get_tms_path(tap_get_state(), tap_get_end_state());
161 int tms_count
= tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
163 gw16012_control(0x0); /* single-bit mode */
165 for (i
= 0; i
< tms_count
; i
++) {
166 tms
= (tms_scan
>> i
) & 1;
167 gw16012_data(tms
<< 1); /* output next TMS bit */
170 tap_set_state(tap_get_end_state());
173 static void gw16012_path_move(struct pathmove_command
*cmd
)
175 int num_states
= cmd
->num_states
;
180 gw16012_control(0x0); /* single-bit mode */
181 if (tap_state_transition(tap_get_state(), false) == cmd
->path
[state_count
])
182 gw16012_data(0x0); /* TCK cycle with TMS low */
183 else if (tap_state_transition(tap_get_state(), true) == cmd
->path
[state_count
])
184 gw16012_data(0x2); /* TCK cycle with TMS high */
186 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
187 tap_state_name(tap_get_state()), tap_state_name(cmd
->path
[state_count
]));
191 tap_set_state(cmd
->path
[state_count
]);
196 tap_set_end_state(tap_get_state());
199 static void gw16012_runtest(int num_cycles
)
201 tap_state_t saved_end_state
= tap_get_end_state();
204 /* only do a state_move when we're not already in IDLE */
205 if (tap_get_state() != TAP_IDLE
) {
206 gw16012_end_state(TAP_IDLE
);
207 gw16012_state_move();
210 for (i
= 0; i
< num_cycles
; i
++) {
211 gw16012_control(0x0); /* single-bit mode */
212 gw16012_data(0x0); /* TMS cycle with TMS low */
215 gw16012_end_state(saved_end_state
);
216 if (tap_get_state() != tap_get_end_state())
217 gw16012_state_move();
220 static void gw16012_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
)
222 int bits_left
= scan_size
;
224 tap_state_t saved_end_state
= tap_get_end_state();
225 uint8_t scan_out
, scan_in
;
227 /* only if we're not already in the correct Shift state */
228 if (!((!ir_scan
&& (tap_get_state() == TAP_DRSHIFT
)) ||
229 (ir_scan
&& (tap_get_state() == TAP_IRSHIFT
)))) {
231 gw16012_end_state(TAP_IRSHIFT
);
233 gw16012_end_state(TAP_DRSHIFT
);
235 gw16012_state_move();
236 gw16012_end_state(saved_end_state
);
239 while (type
== SCAN_OUT
&& ((bits_left
- 1) > 7)) {
240 gw16012_control(0x2); /* seven-bit mode */
241 scan_out
= buf_get_u32(buffer
, bit_count
, 7);
242 gw16012_data(scan_out
);
247 gw16012_control(0x0); /* single-bit mode */
248 while (bits_left
-- > 0) {
251 scan_out
= buf_get_u32(buffer
, bit_count
, 1);
253 if (bits_left
== 0) /* last bit */ {
254 if ((ir_scan
&& (tap_get_end_state() == TAP_IRSHIFT
))
255 || (!ir_scan
&& (tap_get_end_state() == TAP_DRSHIFT
)))
261 gw16012_data(scan_out
| tms
);
263 if (type
!= SCAN_OUT
) {
264 gw16012_input(&scan_in
);
265 buf_set_u32(buffer
, bit_count
, 1, ((scan_in
& 0x08) >> 3));
271 if (!((ir_scan
&& (tap_get_end_state() == TAP_IRSHIFT
)) ||
272 (!ir_scan
&& (tap_get_end_state() == TAP_DRSHIFT
)))) {
275 tap_set_state(TAP_IRPAUSE
);
277 tap_set_state(TAP_DRPAUSE
);
279 if (tap_get_state() != tap_get_end_state())
280 gw16012_state_move();
284 static int gw16012_execute_queue(void)
286 struct jtag_command
*cmd
= jtag_command_queue
; /* currently processed command */
292 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
293 * that wasn't handled by a caller-provided error handler
300 LOG_DEBUG_IO("reset trst: %i srst %i", cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
301 if (cmd
->cmd
.reset
->trst
== 1)
302 tap_set_state(TAP_RESET
);
303 gw16012_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
306 LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd
->cmd
.runtest
->num_cycles
,
307 cmd
->cmd
.runtest
->end_state
);
308 gw16012_end_state(cmd
->cmd
.runtest
->end_state
);
309 gw16012_runtest(cmd
->cmd
.runtest
->num_cycles
);
312 LOG_DEBUG_IO("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
313 gw16012_end_state(cmd
->cmd
.statemove
->end_state
);
314 gw16012_state_move();
317 LOG_DEBUG_IO("pathmove: %i states, end in %i", cmd
->cmd
.pathmove
->num_states
,
318 cmd
->cmd
.pathmove
->path
[cmd
->cmd
.pathmove
->num_states
- 1]);
319 gw16012_path_move(cmd
->cmd
.pathmove
);
322 gw16012_end_state(cmd
->cmd
.scan
->end_state
);
323 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
324 type
= jtag_scan_type(cmd
->cmd
.scan
);
325 LOG_DEBUG_IO("%s scan (%i) %i bit end in %i", (cmd
->cmd
.scan
->ir_scan
) ? "ir" : "dr",
326 type
, scan_size
, cmd
->cmd
.scan
->end_state
);
327 gw16012_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
);
328 if (jtag_read_buffer(buffer
, cmd
->cmd
.scan
) != ERROR_OK
)
329 retval
= ERROR_JTAG_QUEUE_FAILED
;
333 LOG_DEBUG_IO("sleep %" PRIu32
, cmd
->cmd
.sleep
->us
);
334 jtag_sleep(cmd
->cmd
.sleep
->us
);
337 LOG_ERROR("BUG: unknown JTAG command type encountered");
346 #if PARPORT_USE_GIVEIO == 1
347 static int gw16012_get_giveio_access(void)
350 OSVERSIONINFO version
;
352 version
.dwOSVersionInfoSize
= sizeof(version
);
353 if (!GetVersionEx(&version
)) {
357 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
360 h
= CreateFile("\\\\.\\giveio", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
361 FILE_ATTRIBUTE_NORMAL
, NULL
);
362 if (h
== INVALID_HANDLE_VALUE
) {
373 #if PARPORT_USE_PPDEV == 1
375 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
377 #define GW16012_PPDEV_NAME "ppi"
379 static int gw16012_init_ioctls(void)
382 temp
= ioctl(device_handle
, PPCLAIM
);
384 LOG_ERROR("cannot claim device");
385 return ERROR_JTAG_INIT_FAILED
;
388 temp
= PARPORT_MODE_COMPAT
;
389 temp
= ioctl(device_handle
, PPSETMODE
, &temp
);
391 LOG_ERROR(" cannot set compatible mode to device");
392 return ERROR_JTAG_INIT_FAILED
;
395 temp
= IEEE1284_MODE_COMPAT
;
396 temp
= ioctl(device_handle
, PPNEGOT
, &temp
);
398 LOG_ERROR("cannot set compatible 1284 mode to device");
399 return ERROR_JTAG_INIT_FAILED
;
405 #define GW16012_PPDEV_NAME "parport"
407 static int gw16012_init_ioctls(void)
412 #endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
414 static int gw16012_init_device(void)
416 const char *device_name
= GW16012_PPDEV_NAME
;
419 if (device_handle
> 0) {
420 LOG_ERROR("device is already opened");
421 return ERROR_JTAG_INIT_FAILED
;
424 snprintf(buffer
, 256, "/dev/%s%d", device_name
, gw16012_port
);
425 LOG_DEBUG("opening %s...", buffer
);
427 device_handle
= open(buffer
, O_WRONLY
);
428 if (device_handle
< 0) {
429 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
430 return ERROR_JTAG_INIT_FAILED
;
433 LOG_DEBUG("...open");
435 if (gw16012_init_ioctls() != ERROR_OK
)
436 return ERROR_JTAG_INIT_FAILED
;
441 #else /* PARPORT_USE_PPDEV */
443 static int gw16012_init_device(void)
445 if (gw16012_port
== 0) {
446 gw16012_port
= 0x378;
447 LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
450 LOG_DEBUG("requesting privileges for parallel port 0x%" PRIx16
"...", gw16012_port
);
451 #if PARPORT_USE_GIVEIO == 1
452 if (gw16012_get_giveio_access() != 0) {
453 #else /* PARPORT_USE_GIVEIO */
454 if (ioperm(gw16012_port
, 3, 1) != 0) {
455 #endif /* PARPORT_USE_GIVEIO */
456 LOG_ERROR("missing privileges for direct i/o");
457 return ERROR_JTAG_INIT_FAILED
;
459 LOG_DEBUG("...privileges granted");
461 /* make sure parallel port is in right mode (clear tristate and interrupt */
462 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
463 outb(gw16012_port
+ 2, 0x0);
465 outb(0x0, gw16012_port
+ 2);
470 #endif /* PARPORT_USE_PPDEV */
472 static int gw16012_init(void)
476 if (gw16012_init_device() != ERROR_OK
)
477 return ERROR_JTAG_INIT_FAILED
;
479 gw16012_input(&status_port
);
480 gw16012_msb
= (status_port
& 0x80) ^ 0x80;
487 static int gw16012_quit(void)
493 COMMAND_HANDLER(gw16012_handle_parport_port_command
)
496 /* only if the port wasn't overwritten by cmdline */
497 if (gw16012_port
== 0)
498 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], gw16012_port
);
500 LOG_ERROR("The parport port was already configured!");
505 command_print(CMD
, "parport port = %u", gw16012_port
);
510 static const struct command_registration gw16012_command_handlers
[] = {
512 .name
= "parport_port",
513 .handler
= gw16012_handle_parport_port_command
,
514 .mode
= COMMAND_CONFIG
,
515 .help
= "Display the address of the I/O port (e.g. 0x378) "
516 "or the number of the '/dev/parport' device used. "
517 "If a parameter is provided, first change that port.",
518 .usage
= "[port_number]",
520 COMMAND_REGISTRATION_DONE
523 static struct jtag_interface gw16012_interface
= {
524 .execute_queue
= gw16012_execute_queue
,
527 struct adapter_driver gw16012_adapter_driver
= {
529 .transports
= jtag_only
,
530 .commands
= gw16012_command_handlers
,
532 .init
= gw16012_init
,
533 .quit
= gw16012_quit
,
535 .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)