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

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)