- prepare OpenOCD for branching, created ./trunk/
[fw/openocd] / 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 }