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

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)