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

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)