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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 int gw16012_speed(int speed
)
155 static void gw16012_end_state(tap_state_t state
)
157 if (tap_is_state_stable(state
))
158 tap_set_end_state(state
);
160 LOG_ERROR("BUG: %i is not a valid end state", state
);
165 static void gw16012_state_move(void)
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());
171 gw16012_control(0x0); /* single-bit mode */
173 for (i
= 0; i
< tms_count
; i
++) {
174 tms
= (tms_scan
>> i
) & 1;
175 gw16012_data(tms
<< 1); /* output next TMS bit */
178 tap_set_state(tap_get_end_state());
181 static void gw16012_path_move(struct pathmove_command
*cmd
)
183 int num_states
= cmd
->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 */
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
]));
199 tap_set_state(cmd
->path
[state_count
]);
204 tap_set_end_state(tap_get_state());
207 static void gw16012_runtest(int num_cycles
)
209 tap_state_t saved_end_state
= tap_get_end_state();
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();
218 for (i
= 0; i
< num_cycles
; i
++) {
219 gw16012_control(0x0); /* single-bit mode */
220 gw16012_data(0x0); /* TMS cycle with TMS low */
223 gw16012_end_state(saved_end_state
);
224 if (tap_get_state() != tap_get_end_state())
225 gw16012_state_move();
228 static void gw16012_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
)
230 int bits_left
= scan_size
;
232 tap_state_t saved_end_state
= tap_get_end_state();
233 uint8_t scan_out
, scan_in
;
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
)))) {
239 gw16012_end_state(TAP_IRSHIFT
);
241 gw16012_end_state(TAP_DRSHIFT
);
243 gw16012_state_move();
244 gw16012_end_state(saved_end_state
);
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
);
255 gw16012_control(0x0); /* single-bit mode */
256 while (bits_left
-- > 0) {
259 scan_out
= buf_get_u32(buffer
, bit_count
, 1);
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
)))
269 gw16012_data(scan_out
| tms
);
271 if (type
!= SCAN_OUT
) {
272 gw16012_input(&scan_in
);
273 buf_set_u32(buffer
, bit_count
, 1, ((scan_in
& 0x08) >> 3));
279 if (!((ir_scan
&& (tap_get_end_state() == TAP_IRSHIFT
)) ||
280 (!ir_scan
&& (tap_get_end_state() == TAP_DRSHIFT
)))) {
283 tap_set_state(TAP_IRPAUSE
);
285 tap_set_state(TAP_DRPAUSE
);
287 if (tap_get_state() != tap_get_end_state())
288 gw16012_state_move();
292 static int gw16012_execute_queue(void)
294 struct jtag_command
*cmd
= jtag_command_queue
; /* currently processed command */
300 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
301 * that wasn't handled by a caller-provided error handler
308 #ifdef _DEBUG_JTAG_IO_
309 LOG_DEBUG("reset trst: %i srst %i", cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
311 if (cmd
->cmd
.reset
->trst
== 1)
312 tap_set_state(TAP_RESET
);
313 gw16012_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
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
);
320 gw16012_end_state(cmd
->cmd
.runtest
->end_state
);
321 gw16012_runtest(cmd
->cmd
.runtest
->num_cycles
);
324 #ifdef _DEBUG_JTAG_IO_
325 LOG_DEBUG("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
327 gw16012_end_state(cmd
->cmd
.statemove
->end_state
);
328 gw16012_state_move();
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]);
335 gw16012_path_move(cmd
->cmd
.pathmove
);
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
);
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
;
352 #ifdef _DEBUG_JTAG_IO_
353 LOG_DEBUG("sleep %i", cmd
->cmd
.sleep
->us
);
355 jtag_sleep(cmd
->cmd
.sleep
->us
);
358 LOG_ERROR("BUG: unknown JTAG command type encountered");
367 #if PARPORT_USE_GIVEIO == 1
368 static int gw16012_get_giveio_access(void)
371 OSVERSIONINFO version
;
373 version
.dwOSVersionInfoSize
= sizeof version
;
374 if (!GetVersionEx(&version
)) {
378 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
381 h
= CreateFile("\\\\.\\giveio", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
382 FILE_ATTRIBUTE_NORMAL
, NULL
);
383 if (h
== INVALID_HANDLE_VALUE
) {
394 #if PARPORT_USE_PPDEV == 1
396 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
398 #define GW16012_PPDEV_NAME "ppi"
400 static int gw16012_init_ioctls(void)
403 temp
= ioctl(device_handle
, PPCLAIM
);
405 LOG_ERROR("cannot claim device");
406 return ERROR_JTAG_INIT_FAILED
;
409 temp
= PARPORT_MODE_COMPAT
;
410 temp
= ioctl(device_handle
, PPSETMODE
, &temp
);
412 LOG_ERROR(" cannot set compatible mode to device");
413 return ERROR_JTAG_INIT_FAILED
;
416 temp
= IEEE1284_MODE_COMPAT
;
417 temp
= ioctl(device_handle
, PPNEGOT
, &temp
);
419 LOG_ERROR("cannot set compatible 1284 mode to device");
420 return ERROR_JTAG_INIT_FAILED
;
426 #define GW16012_PPDEV_NAME "parport"
428 static int gw16012_init_ioctls(void)
433 #endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
435 static int gw16012_init_device(void)
437 const char *device_name
= GW16012_PPDEV_NAME
;
440 if (device_handle
> 0) {
441 LOG_ERROR("device is already opened");
442 return ERROR_JTAG_INIT_FAILED
;
445 snprintf(buffer
, 256, "/dev/%s%d", device_name
, gw16012_port
);
446 LOG_DEBUG("opening %s...", buffer
);
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
;
454 LOG_DEBUG("...open");
456 if (gw16012_init_ioctls() != ERROR_OK
)
457 return ERROR_JTAG_INIT_FAILED
;
462 #else /* PARPORT_USE_PPDEV */
464 static int gw16012_init_device(void)
466 if (gw16012_port
== 0) {
467 gw16012_port
= 0x378;
468 LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
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
;
480 LOG_DEBUG("...privileges granted");
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);
486 outb(0x0, gw16012_port
+ 2);
491 #endif /* PARPORT_USE_PPDEV */
493 static int gw16012_init(void)
497 if (gw16012_init_device() != ERROR_OK
)
498 return ERROR_JTAG_INIT_FAILED
;
500 gw16012_input(&status_port
);
501 gw16012_msb
= (status_port
& 0x80) ^ 0x80;
508 static int gw16012_quit(void)
514 COMMAND_HANDLER(gw16012_handle_parport_port_command
)
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
);
521 LOG_ERROR("The parport port was already configured!");
526 command_print(CMD_CTX
, "parport port = %u", gw16012_port
);
531 static const struct command_registration gw16012_command_handlers
[] = {
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]",
541 COMMAND_REGISTRATION_DONE
544 struct jtag_interface gw16012_interface
= {
546 .commands
= gw16012_command_handlers
,
548 .init
= gw16012_init
,
549 .quit
= gw16012_quit
,
550 .speed
= gw16012_speed
,
551 .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)