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

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)