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

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)