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, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
25 #include <jtag/interface.h>
26 #include <jtag/commands.h>
29 #define _DEBUG_GW16012_IO_
33 /* -ino: 060521-1036 */
34 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
36 #include <machine/sysarch.h>
37 #include <machine/cpufunc.h>
38 #define ioperm(startport, length, enable) \
39 386_set_ioperm((startport), (length), (enable))
43 #endif /* __FreeBSD__, __FreeBSD_kernel__ */
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
52 #include <linux/parport.h>
53 #include <linux/ppdev.h>
56 #include <sys/ioctl.h>
57 #else /* not PARPORT_USE_PPDEV */
63 #if PARPORT_USE_GIVEIO == 1 && IS_CYGWIN == 1
68 uint16_t gw16012_port
;
70 /* interface variables
72 static uint8_t gw16012_msb
;
73 static uint8_t gw16012_control_value
;
75 #if PARPORT_USE_PPDEV == 1
76 static int device_handle
;
79 static void gw16012_data(uint8_t value
)
81 value
= (value
& 0x7f) | gw16012_msb
;
82 gw16012_msb
^= 0x80; /* toggle MSB */
84 #ifdef _DEBUG_GW16012_IO_
85 LOG_DEBUG("%2.2x", value
);
88 #if PARPORT_USE_PPDEV == 1
89 ioctl(device_handle
, PPWDATA
, &value
);
91 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
92 outb(gw16012_port
, value
);
94 outb(value
, gw16012_port
);
99 static void gw16012_control(uint8_t value
)
101 if (value
!= gw16012_control_value
) {
102 gw16012_control_value
= value
;
104 #ifdef _DEBUG_GW16012_IO_
105 LOG_DEBUG("%2.2x", gw16012_control_value
);
108 #if PARPORT_USE_PPDEV == 1
109 ioctl(device_handle
, PPWCONTROL
, &gw16012_control_value
);
111 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
112 outb(gw16012_port
+ 2, gw16012_control_value
);
114 outb(gw16012_control_value
, gw16012_port
+ 2);
120 static void gw16012_input(uint8_t *value
)
122 #if PARPORT_USE_PPDEV == 1
123 ioctl(device_handle
, PPRSTATUS
, value
);
125 *value
= inb(gw16012_port
+ 1);
128 #ifdef _DEBUG_GW16012_IO_
129 LOG_DEBUG("%2.2x", *value
);
133 /* (1) assert or (0) deassert reset lines */
134 static void gw16012_reset(int trst
, int srst
)
136 LOG_DEBUG("trst: %i, srst: %i", trst
, srst
);
139 gw16012_control(0x0d);
141 gw16012_control(0x0c);
144 gw16012_control(0x0a);
146 gw16012_control(0x0b);
149 static void gw16012_end_state(tap_state_t state
)
151 if (tap_is_state_stable(state
))
152 tap_set_end_state(state
);
154 LOG_ERROR("BUG: %i is not a valid end state", state
);
159 static void gw16012_state_move(void)
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());
165 gw16012_control(0x0); /* single-bit mode */
167 for (i
= 0; i
< tms_count
; i
++) {
168 tms
= (tms_scan
>> i
) & 1;
169 gw16012_data(tms
<< 1); /* output next TMS bit */
172 tap_set_state(tap_get_end_state());
175 static void gw16012_path_move(struct pathmove_command
*cmd
)
177 int num_states
= cmd
->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 */
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
]));
193 tap_set_state(cmd
->path
[state_count
]);
198 tap_set_end_state(tap_get_state());
201 static void gw16012_runtest(int num_cycles
)
203 tap_state_t saved_end_state
= tap_get_end_state();
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();
212 for (i
= 0; i
< num_cycles
; i
++) {
213 gw16012_control(0x0); /* single-bit mode */
214 gw16012_data(0x0); /* TMS cycle with TMS low */
217 gw16012_end_state(saved_end_state
);
218 if (tap_get_state() != tap_get_end_state())
219 gw16012_state_move();
222 static void gw16012_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
)
224 int bits_left
= scan_size
;
226 tap_state_t saved_end_state
= tap_get_end_state();
227 uint8_t scan_out
, scan_in
;
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
)))) {
233 gw16012_end_state(TAP_IRSHIFT
);
235 gw16012_end_state(TAP_DRSHIFT
);
237 gw16012_state_move();
238 gw16012_end_state(saved_end_state
);
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
);
249 gw16012_control(0x0); /* single-bit mode */
250 while (bits_left
-- > 0) {
253 scan_out
= buf_get_u32(buffer
, bit_count
, 1);
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
)))
263 gw16012_data(scan_out
| tms
);
265 if (type
!= SCAN_OUT
) {
266 gw16012_input(&scan_in
);
267 buf_set_u32(buffer
, bit_count
, 1, ((scan_in
& 0x08) >> 3));
273 if (!((ir_scan
&& (tap_get_end_state() == TAP_IRSHIFT
)) ||
274 (!ir_scan
&& (tap_get_end_state() == TAP_DRSHIFT
)))) {
277 tap_set_state(TAP_IRPAUSE
);
279 tap_set_state(TAP_DRPAUSE
);
281 if (tap_get_state() != tap_get_end_state())
282 gw16012_state_move();
286 static int gw16012_execute_queue(void)
288 struct jtag_command
*cmd
= jtag_command_queue
; /* currently processed command */
294 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
295 * that wasn't handled by a caller-provided error handler
302 #ifdef _DEBUG_JTAG_IO_
303 LOG_DEBUG("reset trst: %i srst %i", cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
305 if (cmd
->cmd
.reset
->trst
== 1)
306 tap_set_state(TAP_RESET
);
307 gw16012_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
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
);
314 gw16012_end_state(cmd
->cmd
.runtest
->end_state
);
315 gw16012_runtest(cmd
->cmd
.runtest
->num_cycles
);
318 #ifdef _DEBUG_JTAG_IO_
319 LOG_DEBUG("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
321 gw16012_end_state(cmd
->cmd
.statemove
->end_state
);
322 gw16012_state_move();
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]);
329 gw16012_path_move(cmd
->cmd
.pathmove
);
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
);
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
;
346 #ifdef _DEBUG_JTAG_IO_
347 LOG_DEBUG("sleep %i", cmd
->cmd
.sleep
->us
);
349 jtag_sleep(cmd
->cmd
.sleep
->us
);
352 LOG_ERROR("BUG: unknown JTAG command type encountered");
361 #if PARPORT_USE_GIVEIO == 1
362 static int gw16012_get_giveio_access(void)
365 OSVERSIONINFO version
;
367 version
.dwOSVersionInfoSize
= sizeof version
;
368 if (!GetVersionEx(&version
)) {
372 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
375 h
= CreateFile("\\\\.\\giveio", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
376 FILE_ATTRIBUTE_NORMAL
, NULL
);
377 if (h
== INVALID_HANDLE_VALUE
) {
388 #if PARPORT_USE_PPDEV == 1
390 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
392 #define GW16012_PPDEV_NAME "ppi"
394 static int gw16012_init_ioctls(void)
397 temp
= ioctl(device_handle
, PPCLAIM
);
399 LOG_ERROR("cannot claim device");
400 return ERROR_JTAG_INIT_FAILED
;
403 temp
= PARPORT_MODE_COMPAT
;
404 temp
= ioctl(device_handle
, PPSETMODE
, &temp
);
406 LOG_ERROR(" cannot set compatible mode to device");
407 return ERROR_JTAG_INIT_FAILED
;
410 temp
= IEEE1284_MODE_COMPAT
;
411 temp
= ioctl(device_handle
, PPNEGOT
, &temp
);
413 LOG_ERROR("cannot set compatible 1284 mode to device");
414 return ERROR_JTAG_INIT_FAILED
;
420 #define GW16012_PPDEV_NAME "parport"
422 static int gw16012_init_ioctls(void)
427 #endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
429 static int gw16012_init_device(void)
431 const char *device_name
= GW16012_PPDEV_NAME
;
434 if (device_handle
> 0) {
435 LOG_ERROR("device is already opened");
436 return ERROR_JTAG_INIT_FAILED
;
439 snprintf(buffer
, 256, "/dev/%s%d", device_name
, gw16012_port
);
440 LOG_DEBUG("opening %s...", buffer
);
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
;
448 LOG_DEBUG("...open");
450 if (gw16012_init_ioctls() != ERROR_OK
)
451 return ERROR_JTAG_INIT_FAILED
;
456 #else /* PARPORT_USE_PPDEV */
458 static int gw16012_init_device(void)
460 if (gw16012_port
== 0) {
461 gw16012_port
= 0x378;
462 LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
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
;
474 LOG_DEBUG("...privileges granted");
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);
480 outb(0x0, gw16012_port
+ 2);
485 #endif /* PARPORT_USE_PPDEV */
487 static int gw16012_init(void)
491 if (gw16012_init_device() != ERROR_OK
)
492 return ERROR_JTAG_INIT_FAILED
;
494 gw16012_input(&status_port
);
495 gw16012_msb
= (status_port
& 0x80) ^ 0x80;
502 static int gw16012_quit(void)
508 COMMAND_HANDLER(gw16012_handle_parport_port_command
)
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
);
515 LOG_ERROR("The parport port was already configured!");
520 command_print(CMD_CTX
, "parport port = %u", gw16012_port
);
525 static const struct command_registration gw16012_command_handlers
[] = {
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]",
535 COMMAND_REGISTRATION_DONE
538 struct jtag_interface gw16012_interface
= {
540 .commands
= gw16012_command_handlers
,
542 .init
= gw16012_init
,
543 .quit
= gw16012_quit
,
544 .execute_queue
= gw16012_execute_queue
,
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)