- Added support for native MinGW builds (thanks to Spencer Oliver and Michael Fischer...
[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 snprintf(buffer, 256, "/dev/parport%d", parport_port);
314 device_handle = open(buffer, O_WRONLY);
315
316 if (device_handle<0)
317 {
318 ERROR("cannot open device. check it exists and that user read and write rights are set");
319 return ERROR_JTAG_INIT_FAILED;
320 }
321
322 i=ioctl(device_handle, PPCLAIM);
323 if (i<0)
324 {
325 ERROR("cannot claim device");
326 return ERROR_JTAG_INIT_FAILED;
327 }
328
329 i = PARPORT_MODE_COMPAT;
330 i= ioctl(device_handle, PPSETMODE, & i);
331 if (i<0)
332 {
333 ERROR(" cannot set compatible mode to device");
334 return ERROR_JTAG_INIT_FAILED;
335 }
336
337 i = IEEE1284_MODE_COMPAT;
338 i = ioctl(device_handle, PPNEGOT, & i);
339 if (i<0)
340 {
341 ERROR("cannot set compatible 1284 mode to device");
342 return ERROR_JTAG_INIT_FAILED;
343 }
344 #else
345 if (parport_port == 0)
346 {
347 parport_port = 0x378;
348 WARNING("No parport port specified, using default '0x378' (LPT1)");
349 }
350
351 dataport = parport_port;
352 statusport = parport_port + 1;
353
354 #if PARPORT_USE_GIVEIO == 1
355 if (parport_get_giveio_access() != 0)
356 #else /* PARPORT_USE_GIVEIO */
357 if (ioperm(dataport, 3, 1) != 0)
358 #endif /* PARPORT_USE_GIVEIO */
359 {
360 ERROR("missing privileges for direct i/o");
361 return ERROR_JTAG_INIT_FAILED;
362 }
363 #endif /* PARPORT_USE_PPDEV */
364
365 parport_reset(0, 0);
366 parport_write(0, 0, 0);
367
368 bitbang_interface = &parport_bitbang;
369
370 return ERROR_OK;
371 }
372
373 int parport_quit(void)
374 {
375
376 return ERROR_OK;
377 }
378
379 int parport_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
380 {
381 if (argc == 0)
382 return ERROR_OK;
383
384 /* only if the port wasn't overwritten by cmdline */
385 if (parport_port == 0)
386 parport_port = strtoul(args[0], NULL, 0);
387
388 return ERROR_OK;
389 }
390
391 int parport_handle_parport_cable_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
392 {
393 if (argc == 0)
394 return ERROR_OK;
395
396 /* only if the cable name wasn't overwritten by cmdline */
397 if (parport_cable == 0)
398 {
399 parport_cable = malloc(strlen(args[0]) + sizeof(char));
400 strcpy(parport_cable, args[0]);
401 }
402
403 return ERROR_OK;
404 }

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)