8265ada8ad339efd8038af80c1461de68f5a8b48
[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 #include "config.h"
21 #include "log.h"
22 #include "jtag.h"
23 #include "bitbang.h"
24
25 /* system includes */
26 // -ino: 060521-1036
27 #ifdef __FreeBSD__
28 #include <sys/types.h>
29 #include <machine/sysarch.h>
30 #include <machine/cpufunc.h>
31 #define ioperm(startport,length,enable)\
32 i386_set_ioperm((startport), (length), (enable))
33 #else
34 #include <sys/io.h>
35 #endif
36
37 #include <string.h>
38 #include <stdlib.h>
39 #include <stdio.h>
40
41 #if PARPORT_USE_PPDEV == 1
42 #include <linux/parport.h>
43 #include <linux/ppdev.h>
44 #include <fcntl.h>
45 #include <sys/ioctl.h>
46 #endif
47
48 /* parallel port cable description
49 */
50 typedef struct cable_s
51 {
52 char* name;
53 u8 TDO_MASK; /* status port bit containing current TDO value */
54 u8 TRST_MASK; /* data port bit for TRST */
55 u8 TMS_MASK; /* data port bit for TMS */
56 u8 TCK_MASK; /* data port bit for TCK */
57 u8 TDI_MASK; /* data port bit for TDI */
58 u8 SRST_MASK; /* data port bit for SRST */
59 u8 OUTPUT_INVERT; /* data port bits that should be inverted */
60 u8 INPUT_INVERT; /* status port that should be inverted */
61 u8 PORT_INIT; /* initialize data port with this value */
62 } cable_t;
63
64 cable_t cables[] =
65 {
66 /* name tdo trst tms tck tdi srst o_inv i_inv init */
67 { "wiggler", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80 },
68 { "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80 },
69 { "chameleon", 0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00 },
70 { "dlc5", 0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10 },
71 { "triton", 0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00 },
72 { NULL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
73 };
74
75 /* configuration */
76 char* parport_cable;
77 unsigned long parport_port;
78
79 /* interface variables
80 */
81 static cable_t* cable;
82 static u8 dataport_value = 0x0;
83
84 #if PARPORT_USE_PPDEV == 1
85 static int device_handle;
86 #else
87 static unsigned long dataport;
88 static unsigned long statusport;
89 #endif
90
91 /* low level command set
92 */
93 int parport_read(void);
94 void parport_write(int tck, int tms, int tdi);
95 void parport_reset(int trst, int srst);
96
97 int parport_speed(int speed);
98 int parport_register_commands(struct command_context_s *cmd_ctx);
99 int parport_init(void);
100 int parport_quit(void);
101
102 /* interface commands */
103 int parport_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
104 int parport_handle_parport_cable_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
105
106 jtag_interface_t parport_interface =
107 {
108 .name = "parport",
109
110 .execute_queue = bitbang_execute_queue,
111
112 .support_statemove = 0,
113
114 .speed = parport_speed,
115 .register_commands = parport_register_commands,
116 .init = parport_init,
117 .quit = parport_quit,
118 };
119
120 bitbang_interface_t parport_bitbang =
121 {
122 .read = parport_read,
123 .write = parport_write,
124 .reset = parport_reset
125 };
126
127 int parport_read(void)
128 {
129 int data = 0;
130
131 #if PARPORT_USE_PPDEV == 1
132 ioctl(device_handle, PPRSTATUS, & data);
133 #else
134 data = inb(statusport);
135 #endif
136
137 if ((data ^ cable->INPUT_INVERT) & cable->TDO_MASK)
138 return 1;
139 else
140 return 0;
141 }
142
143 void parport_write(int tck, int tms, int tdi)
144 {
145 u8 output;
146 int i = jtag_speed + 1;
147
148 if (tck)
149 dataport_value |= cable->TCK_MASK;
150 else
151 dataport_value &= ~cable->TCK_MASK;
152
153 if (tms)
154 dataport_value |= cable->TMS_MASK;
155 else
156 dataport_value &= ~cable->TMS_MASK;
157
158 if (tdi)
159 dataport_value |= cable->TDI_MASK;
160 else
161 dataport_value &= ~cable->TDI_MASK;
162
163 output = dataport_value ^ cable->OUTPUT_INVERT;
164
165 while (i-- > 0)
166 #if PARPORT_USE_PPDEV == 1
167 ioctl(device_handle, PPWDATA, &output);
168 #else
169 #ifdef __FreeBSD__
170 outb(dataport, output);
171 #else
172 outb(output, dataport);
173 #endif
174 #endif
175 }
176
177 /* (1) assert or (0) deassert reset lines */
178 void parport_reset(int trst, int srst)
179 {
180 u8 output;
181 DEBUG("trst: %i, srst: %i", trst, srst);
182
183 if (trst == 0)
184 dataport_value |= cable->TRST_MASK;
185 else if (trst == 1)
186 dataport_value &= ~cable->TRST_MASK;
187
188 if (srst == 0)
189 dataport_value |= cable->SRST_MASK;
190 else if (srst == 1)
191 dataport_value &= ~cable->SRST_MASK;
192
193 output = dataport_value ^ cable->OUTPUT_INVERT;
194
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
207 int parport_speed(int speed)
208 {
209 jtag_speed = speed;
210
211 return ERROR_OK;
212 }
213
214 int parport_register_commands(struct command_context_s *cmd_ctx)
215 {
216 register_command(cmd_ctx, NULL, "parport_port", parport_handle_parport_port_command,
217 COMMAND_CONFIG, NULL);
218 register_command(cmd_ctx, NULL, "parport_cable", parport_handle_parport_cable_command,
219 COMMAND_CONFIG, NULL);
220
221 return ERROR_OK;
222 }
223
224 int parport_init(void)
225 {
226 cable_t *cur_cable;
227 #if PARPORT_USE_PPDEV == 1
228 char buffer[256];
229 int i = 0;
230 #endif
231
232 cur_cable = cables;
233
234 if ((parport_cable == NULL) || (parport_cable[0] == 0))
235 {
236 parport_cable = "wiggler";
237 WARNING("No parport cable specified, using default 'wiggler'");
238 }
239
240 while (cur_cable->name)
241 {
242 if (strcmp(cur_cable->name, parport_cable) == 0)
243 {
244 cable = cur_cable;
245 break;
246 }
247 cur_cable++;
248 }
249
250 if (!cable)
251 {
252 ERROR("No matching cable found for %s", parport_cable);
253 return ERROR_JTAG_INIT_FAILED;
254 }
255
256 dataport_value = cable->PORT_INIT;
257
258 #if PARPORT_USE_PPDEV == 1
259 if (device_handle>0)
260 {
261 ERROR("device is already opened");
262 return ERROR_JTAG_INIT_FAILED;
263 }
264
265 snprintf(buffer, 256, "/dev/parport%d", parport_port);
266 device_handle = open(buffer, O_WRONLY);
267
268 if (device_handle<0)
269 {
270 ERROR("cannot open device. check it exists and that user read and write rights are set");
271 return ERROR_JTAG_INIT_FAILED;
272 }
273
274 i=ioctl(device_handle, PPCLAIM);
275 if (i<0)
276 {
277 ERROR("cannot claim device");
278 return ERROR_JTAG_INIT_FAILED;
279 }
280
281 i = PARPORT_MODE_COMPAT;
282 i= ioctl(device_handle, PPSETMODE, & i);
283 if (i<0)
284 {
285 ERROR(" cannot set compatible mode to device");
286 return ERROR_JTAG_INIT_FAILED;
287 }
288
289 i = IEEE1284_MODE_COMPAT;
290 i = ioctl(device_handle, PPNEGOT, & i);
291 if (i<0)
292 {
293 ERROR("cannot set compatible 1284 mode to device");
294 return ERROR_JTAG_INIT_FAILED;
295 }
296 #else
297 if (parport_port == 0)
298 {
299 parport_port = 0x378;
300 WARNING("No parport port specified, using default '0x378' (LPT1)");
301 }
302
303 dataport = parport_port;
304 statusport = parport_port + 1;
305
306 if (ioperm(dataport, 3, 1) != 0) {
307 ERROR("missing privileges for direct i/o");
308 return ERROR_JTAG_INIT_FAILED;
309 }
310 #endif
311
312 parport_reset(0, 0);
313 parport_write(0, 0, 0);
314
315 bitbang_interface = &parport_bitbang;
316
317 return ERROR_OK;
318 }
319
320 int parport_quit(void)
321 {
322
323 return ERROR_OK;
324 }
325
326 int parport_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
327 {
328 if (argc == 0)
329 return ERROR_OK;
330
331 /* only if the port wasn't overwritten by cmdline */
332 if (parport_port == 0)
333 parport_port = strtoul(args[0], NULL, 0);
334
335 return ERROR_OK;
336 }
337
338 int parport_handle_parport_cable_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
339 {
340 if (argc == 0)
341 return ERROR_OK;
342
343 /* only if the cable name wasn't overwritten by cmdline */
344 if (parport_cable == 0)
345 {
346 parport_cable = malloc(strlen(args[0]) + sizeof(char));
347 strcpy(parport_cable, args[0]);
348 }
349
350 return ERROR_OK;
351 }

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)