- disabled FT2232 debug output (that code should be fairly stable)
[openocd.git] / src / jtag / parport.c
1 /***************************************************************************
2 * Copyright (C) 2005 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, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "replacements.h"
25
26 #include "jtag.h"
27 #include "bitbang.h"
28
29 /* system includes */
30 // -ino: 060521-1036
31 #ifdef __FreeBSD__
32
33 #include <sys/types.h>
34 #include <machine/sysarch.h>
35 #include <machine/cpufunc.h>
36 #define ioperm(startport,length,enable)\
37 i386_set_ioperm((startport), (length), (enable))
38
39 #else
40
41 #ifndef _WIN32
42 #include <sys/io.h>
43 #else
44 #include "errno.h"
45 #endif /* _WIN32 */
46
47 #endif /* __FreeBSD__ */
48
49 #include <string.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52
53 #if PARPORT_USE_PPDEV == 1
54 #ifdef __FreeBSD__
55 #include <dev/ppbus/ppi.h>
56 #include <dev/ppbus/ppbconf.h>
57 #define PPRSTATUS PPIGSTATUS
58 #define PPWDATA PPISDATA
59 #else
60 #include <linux/parport.h>
61 #include <linux/ppdev.h>
62 #endif
63 #include <fcntl.h>
64 #include <sys/ioctl.h>
65 #endif
66
67 #if PARPORT_USE_GIVEIO == 1
68 #if IS_CYGWIN == 1
69 #include <windows.h>
70 #include <errno.h>
71 #undef ERROR
72 #endif
73 #endif
74
75 #include "log.h"
76
77 /* parallel port cable description
78 */
79 typedef struct cable_s
80 {
81 char* name;
82 u8 TDO_MASK; /* status port bit containing current TDO value */
83 u8 TRST_MASK; /* data port bit for TRST */
84 u8 TMS_MASK; /* data port bit for TMS */
85 u8 TCK_MASK; /* data port bit for TCK */
86 u8 TDI_MASK; /* data port bit for TDI */
87 u8 SRST_MASK; /* data port bit for SRST */
88 u8 OUTPUT_INVERT; /* data port bits that should be inverted */
89 u8 INPUT_INVERT; /* status port that should be inverted */
90 u8 PORT_INIT; /* initialize data port with this value */
91 } cable_t;
92
93 cable_t cables[] =
94 {
95 /* name tdo trst tms tck tdi srst o_inv i_inv init */
96 { "wiggler", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80 },
97 { "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80 },
98 { "chameleon", 0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00 },
99 { "dlc5", 0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10 },
100 { "triton", 0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00 },
101 { "lattice", 0x40, 0x10, 0x04, 0x02, 0x01, 0x08, 0x00, 0x00, 0x18 },
102 { NULL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
103 };
104
105 /* configuration */
106 char* parport_cable;
107 unsigned long parport_port;
108
109 /* interface variables
110 */
111 static cable_t* cable;
112 static u8 dataport_value = 0x0;
113
114 #if PARPORT_USE_PPDEV == 1
115 static int device_handle;
116 #else
117 static unsigned long dataport;
118 static unsigned long statusport;
119 #endif
120
121 /* low level command set
122 */
123 int parport_read(void);
124 void parport_write(int tck, int tms, int tdi);
125 void parport_reset(int trst, int srst);
126
127 int parport_speed(int speed);
128 int parport_register_commands(struct command_context_s *cmd_ctx);
129 int parport_init(void);
130 int parport_quit(void);
131
132 /* interface commands */
133 int parport_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
134 int parport_handle_parport_cable_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
135
136 jtag_interface_t parport_interface =
137 {
138 .name = "parport",
139
140 .execute_queue = bitbang_execute_queue,
141
142 .support_pathmove = 1,
143
144 .speed = parport_speed,
145 .register_commands = parport_register_commands,
146 .init = parport_init,
147 .quit = parport_quit,
148 };
149
150 bitbang_interface_t parport_bitbang =
151 {
152 .read = parport_read,
153 .write = parport_write,
154 .reset = parport_reset
155 };
156
157 int parport_read(void)
158 {
159 int data = 0;
160
161 #if PARPORT_USE_PPDEV == 1
162 ioctl(device_handle, PPRSTATUS, & data);
163 #else
164 data = inb(statusport);
165 #endif
166
167 if ((data ^ cable->INPUT_INVERT) & cable->TDO_MASK)
168 return 1;
169 else
170 return 0;
171 }
172
173 void parport_write(int tck, int tms, int tdi)
174 {
175 u8 output;
176 int i = jtag_speed + 1;
177
178 if (tck)
179 dataport_value |= cable->TCK_MASK;
180 else
181 dataport_value &= ~cable->TCK_MASK;
182
183 if (tms)
184 dataport_value |= cable->TMS_MASK;
185 else
186 dataport_value &= ~cable->TMS_MASK;
187
188 if (tdi)
189 dataport_value |= cable->TDI_MASK;
190 else
191 dataport_value &= ~cable->TDI_MASK;
192
193 output = dataport_value ^ cable->OUTPUT_INVERT;
194
195 while (i-- > 0)
196 #if PARPORT_USE_PPDEV == 1
197 ioctl(device_handle, PPWDATA, &output);
198 #else
199 #ifdef __FreeBSD__
200 outb(dataport, output);
201 #else
202 outb(output, dataport);
203 #endif
204 #endif
205 }
206
207 /* (1) assert or (0) deassert reset lines */
208 void parport_reset(int trst, int srst)
209 {
210 u8 output;
211 DEBUG("trst: %i, srst: %i", trst, srst);
212
213 if (trst == 0)
214 dataport_value |= cable->TRST_MASK;
215 else if (trst == 1)
216 dataport_value &= ~cable->TRST_MASK;
217
218 if (srst == 0)
219 dataport_value |= cable->SRST_MASK;
220 else if (srst == 1)
221 dataport_value &= ~cable->SRST_MASK;
222
223 output = dataport_value ^ cable->OUTPUT_INVERT;
224
225 #if PARPORT_USE_PPDEV == 1
226 ioctl(device_handle, PPWDATA, &output);
227 #else
228 #ifdef __FreeBSD__
229 outb(dataport, output);
230 #else
231 outb(output, dataport);
232 #endif
233 #endif
234
235 }
236
237 int parport_speed(int speed)
238 {
239 jtag_speed = speed;
240
241 return ERROR_OK;
242 }
243
244 int parport_register_commands(struct command_context_s *cmd_ctx)
245 {
246 register_command(cmd_ctx, NULL, "parport_port", parport_handle_parport_port_command,
247 COMMAND_CONFIG, NULL);
248 register_command(cmd_ctx, NULL, "parport_cable", parport_handle_parport_cable_command,
249 COMMAND_CONFIG, NULL);
250
251 return ERROR_OK;
252 }
253
254 #if PARPORT_USE_GIVEIO == 1
255 int parport_get_giveio_access()
256 {
257 HANDLE h;
258 OSVERSIONINFO version;
259
260 version.dwOSVersionInfoSize = sizeof version;
261 if (!GetVersionEx( &version )) {
262 errno = EINVAL;
263 return -1;
264 }
265 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
266 return 0;
267
268 h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
269 if (h == INVALID_HANDLE_VALUE) {
270 errno = ENODEV;
271 return -1;
272 }
273
274 CloseHandle( h );
275
276 return 0;
277 }
278 #endif
279
280 int parport_init(void)
281 {
282 cable_t *cur_cable;
283 #if PARPORT_USE_PPDEV == 1
284 char buffer[256];
285 int i = 0;
286 #endif
287
288 cur_cable = cables;
289
290 if ((parport_cable == NULL) || (parport_cable[0] == 0))
291 {
292 parport_cable = "wiggler";
293 WARNING("No parport cable specified, using default 'wiggler'");
294 }
295
296 while (cur_cable->name)
297 {
298 if (strcmp(cur_cable->name, parport_cable) == 0)
299 {
300 cable = cur_cable;
301 break;
302 }
303 cur_cable++;
304 }
305
306 if (!cable)
307 {
308 ERROR("No matching cable found for %s", parport_cable);
309 return ERROR_JTAG_INIT_FAILED;
310 }
311
312 dataport_value = cable->PORT_INIT;
313
314 #if PARPORT_USE_PPDEV == 1
315 if (device_handle > 0)
316 {
317 ERROR("device is already opened");
318 return ERROR_JTAG_INIT_FAILED;
319 }
320
321 #ifdef __FreeBSD__
322 DEBUG("opening /dev/ppi%d...", parport_port);
323
324 snprintf(buffer, 256, "/dev/ppi%d", parport_port);
325 device_handle = open(buffer, O_WRONLY);
326 #else /* not __Free_BSD */
327 DEBUG("opening /dev/parport%d...", parport_port);
328
329 snprintf(buffer, 256, "/dev/parport%d", parport_port);
330 device_handle = open(buffer, O_WRONLY);
331 #endif /* __FreeBSD__ */
332
333 if (device_handle < 0)
334 {
335 ERROR("cannot open device. check it exists and that user read and write rights are set");
336 return ERROR_JTAG_INIT_FAILED;
337 }
338
339 DEBUG("...open");
340
341 #ifndef __FreeBSD__
342 i=ioctl(device_handle, PPCLAIM);
343 if (i<0)
344 {
345 ERROR("cannot claim device");
346 return ERROR_JTAG_INIT_FAILED;
347 }
348
349 i = PARPORT_MODE_COMPAT;
350 i= ioctl(device_handle, PPSETMODE, & i);
351 if (i<0)
352 {
353 ERROR(" cannot set compatible mode to device");
354 return ERROR_JTAG_INIT_FAILED;
355 }
356
357 i = IEEE1284_MODE_COMPAT;
358 i = ioctl(device_handle, PPNEGOT, & i);
359 if (i<0)
360 {
361 ERROR("cannot set compatible 1284 mode to device");
362 return ERROR_JTAG_INIT_FAILED;
363 }
364 #endif /* not __Free_BSD__ */
365
366 #else /* not PARPORT_USE_PPDEV */
367 if (parport_port == 0)
368 {
369 parport_port = 0x378;
370 WARNING("No parport port specified, using default '0x378' (LPT1)");
371 }
372
373 dataport = parport_port;
374 statusport = parport_port + 1;
375
376 DEBUG("requesting privileges for parallel port 0x%x...", dataport);
377 #if PARPORT_USE_GIVEIO == 1
378 if (parport_get_giveio_access() != 0)
379 #else /* PARPORT_USE_GIVEIO */
380 if (ioperm(dataport, 3, 1) != 0)
381 #endif /* PARPORT_USE_GIVEIO */
382 {
383 ERROR("missing privileges for direct i/o");
384 return ERROR_JTAG_INIT_FAILED;
385 }
386 DEBUG("...privileges granted");
387
388 /* make sure parallel port is in right mode (clear tristate and interrupt */
389 #ifdef __FreeBSD__
390 outb(parport_port + 2, 0x0);
391 #else
392 outb(0x0, dataport);
393 #endif
394
395 #endif /* PARPORT_USE_PPDEV */
396
397 parport_reset(0, 0);
398 parport_write(0, 0, 0);
399
400 bitbang_interface = &parport_bitbang;
401
402 return ERROR_OK;
403 }
404
405 int parport_quit(void)
406 {
407
408 return ERROR_OK;
409 }
410
411 int parport_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
412 {
413 if (argc == 0)
414 return ERROR_OK;
415
416 /* only if the port wasn't overwritten by cmdline */
417 if (parport_port == 0)
418 parport_port = strtoul(args[0], NULL, 0);
419
420 return ERROR_OK;
421 }
422
423 int parport_handle_parport_cable_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
424 {
425 if (argc == 0)
426 return ERROR_OK;
427
428 /* only if the cable name wasn't overwritten by cmdline */
429 if (parport_cable == 0)
430 {
431 parport_cable = malloc(strlen(args[0]) + sizeof(char));
432 strcpy(parport_cable, args[0]);
433 }
434
435 return ERROR_OK;
436 }

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)