Zach Welch <zw@superlucidity.net> use static keyword in jtag layer and drivers
[fw/openocd] / src / jtag / gw16012.c
1 /***************************************************************************
2  *   Copyright (C) 2006 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
28 #if 1
29 #define _DEBUG_GW16012_IO_
30 #endif
31
32 /* system includes */
33 /*  -ino: 060521-1036 */
34 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
35
36 #include <sys/types.h>
37 #include <machine/sysarch.h>
38 #include <machine/cpufunc.h>
39 #define ioperm(startport,length,enable)\
40   i386_set_ioperm((startport), (length), (enable))
41
42 #else
43
44 #ifdef _WIN32
45 #include "errno.h"
46 #endif /* _WIN32 */
47
48 #endif /* __FreeBSD__, __FreeBSD_kernel__ */
49
50 #include <string.h>
51 #include <stdlib.h>
52
53 #if PARPORT_USE_PPDEV == 1
54 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
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 #else /* not PARPORT_USE_PPDEV */
66 #ifndef _WIN32
67 #include <sys/io.h>
68 #endif
69 #endif
70
71 #if PARPORT_USE_GIVEIO == 1
72 #if IS_CYGWIN == 1
73 #include <windows.h>
74 #include <errno.h>
75 #endif
76 #endif
77
78 #include "log.h"
79
80 /* configuration */
81 u16 gw16012_port;
82
83 /* interface variables
84  */
85 static u8 gw16012_msb = 0x0;
86 static u8 gw16012_control_value = 0x0;
87
88 #if PARPORT_USE_PPDEV == 1
89 static int device_handle;
90 #endif
91
92 static int gw16012_execute_queue(void);
93 static int gw16012_register_commands(struct command_context_s *cmd_ctx);
94 static int gw16012_speed(int speed);
95 static int gw16012_init(void);
96 static int gw16012_quit(void);
97
98 static int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
99
100 jtag_interface_t gw16012_interface =
101 {
102         .name = "gw16012",
103
104         .execute_queue = gw16012_execute_queue,
105
106         .speed = gw16012_speed,
107         .register_commands = gw16012_register_commands,
108         .init = gw16012_init,
109         .quit = gw16012_quit,
110 };
111
112 static int gw16012_register_commands(struct command_context_s *cmd_ctx)
113 {
114         register_command(cmd_ctx, NULL, "parport_port", gw16012_handle_parport_port_command,
115                                          COMMAND_CONFIG, NULL);
116
117         return ERROR_OK;
118 }
119
120 static void gw16012_data(u8 value)
121 {
122         value = (value & 0x7f) | gw16012_msb;
123         gw16012_msb ^= 0x80; /* toggle MSB */
124
125 #ifdef _DEBUG_GW16012_IO_
126         LOG_DEBUG("%2.2x", value);
127 #endif
128
129         #if PARPORT_USE_PPDEV == 1
130                 ioctl(device_handle, PPWDATA, &value);
131         #else
132                 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
133                         outb(gw16012_port, value);
134                 #else
135                         outb(value, gw16012_port);
136                 #endif
137         #endif
138 }
139
140 static void gw16012_control(u8 value)
141 {
142         if (value != gw16012_control_value)
143         {
144                 gw16012_control_value = value;
145
146 #ifdef _DEBUG_GW16012_IO_
147                 LOG_DEBUG("%2.2x", gw16012_control_value);
148 #endif
149
150                 #if PARPORT_USE_PPDEV == 1
151                         ioctl(device_handle, PPWCONTROL, &gw16012_control_value);
152                 #else
153                         #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
154                                 outb(gw16012_port + 2, gw16012_control_value);
155                         #else
156                                 outb(gw16012_control_value, gw16012_port + 2);
157                         #endif
158                 #endif
159         }
160 }
161
162 static void gw16012_input(u8 *value)
163 {
164         #if PARPORT_USE_PPDEV == 1
165                 ioctl(device_handle, PPRSTATUS, value);
166         #else
167                 *value = inb(gw16012_port + 1);
168         #endif
169
170 #ifdef _DEBUG_GW16012_IO_
171         LOG_DEBUG("%2.2x", *value);
172 #endif
173 }
174
175 /* (1) assert or (0) deassert reset lines */
176 static void gw16012_reset(int trst, int srst)
177 {
178         LOG_DEBUG("trst: %i, srst: %i", trst, srst);
179
180         if (trst == 0)
181                 gw16012_control(0x0d);
182         else if (trst == 1)
183                 gw16012_control(0x0c);
184
185         if (srst == 0)
186                 gw16012_control(0x0a);
187         else if (srst == 1)
188                 gw16012_control(0x0b);
189 }
190
191 static int gw16012_speed(int speed)
192 {
193
194         return ERROR_OK;
195 }
196
197 static void gw16012_end_state(tap_state_t state)
198 {
199         if (tap_is_state_stable(state))
200                 tap_set_end_state(state);
201         else
202         {
203                 LOG_ERROR("BUG: %i is not a valid end state", state);
204                 exit(-1);
205         }
206 }
207
208 static void gw16012_state_move(void)
209 {
210         int i=0, tms=0;
211         u8 tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
212
213         gw16012_control(0x0); /* single-bit mode */
214
215         for (i = 0; i < 7; i++)
216         {
217                 tms = (tms_scan >> i) & 1;
218                 gw16012_data(tms << 1); /* output next TMS bit */
219         }
220
221         tap_set_state(tap_get_end_state());
222 }
223
224 static void gw16012_path_move(pathmove_command_t *cmd)
225 {
226         int num_states = cmd->num_states;
227         int state_count;
228
229         state_count = 0;
230         while (num_states)
231         {
232                 gw16012_control(0x0); /* single-bit mode */
233                 if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
234                 {
235                         gw16012_data(0x0); /* TCK cycle with TMS low */
236                 }
237                 else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
238                 {
239                         gw16012_data(0x2); /* TCK cycle with TMS high */
240                 }
241                 else
242                 {
243                         LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count]));
244                         exit(-1);
245                 }
246
247                 tap_set_state(cmd->path[state_count]);
248                 state_count++;
249                 num_states--;
250         }
251
252         tap_set_end_state(tap_get_state());
253 }
254
255 static void gw16012_runtest(int num_cycles)
256 {
257         tap_state_t saved_end_state = tap_get_end_state();
258         int i;
259
260         /* only do a state_move when we're not already in IDLE */
261         if (tap_get_state() != TAP_IDLE)
262         {
263                 gw16012_end_state(TAP_IDLE);
264                 gw16012_state_move();
265         }
266
267         for (i = 0; i < num_cycles; i++)
268         {
269                 gw16012_control(0x0); /* single-bit mode */
270                 gw16012_data(0x0); /* TMS cycle with TMS low */
271         }
272
273         gw16012_end_state(saved_end_state);
274         if (tap_get_state() != tap_get_end_state())
275                 gw16012_state_move();
276 }
277
278 static void gw16012_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
279 {
280         int bits_left = scan_size;
281         int bit_count = 0;
282         tap_state_t saved_end_state = tap_get_end_state();
283         u8 scan_out, scan_in;
284
285         /* only if we're not already in the correct Shift state */
286         if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || (ir_scan && (tap_get_state() == TAP_IRSHIFT))))
287         {
288                 if (ir_scan)
289                         gw16012_end_state(TAP_IRSHIFT);
290                 else
291                         gw16012_end_state(TAP_DRSHIFT);
292
293                 gw16012_state_move();
294                 gw16012_end_state(saved_end_state);
295         }
296
297         while (type == SCAN_OUT && ((bits_left - 1) > 7))
298         {
299                 gw16012_control(0x2); /* seven-bit mode */
300                 scan_out = buf_get_u32(buffer, bit_count, 7);
301                 gw16012_data(scan_out);
302                 bit_count += 7;
303                 bits_left -= 7;
304         }
305
306         gw16012_control(0x0); /* single-bit mode */
307         while (bits_left-- > 0)
308         {
309                 u8 tms = 0;
310
311                 scan_out = buf_get_u32(buffer, bit_count, 1);
312
313                 if (bits_left == 0) /* last bit */
314                 {
315                         if ((ir_scan && (tap_get_end_state() == TAP_IRSHIFT))
316                                 || (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT)))
317                         {
318                                 tms = 0;
319                         }
320                         else
321                         {
322                                 tms = 2;
323                         }
324                 }
325
326                 gw16012_data(scan_out | tms);
327
328                 if (type != SCAN_OUT)
329                 {
330                         gw16012_input(&scan_in);
331                         buf_set_u32(buffer, bit_count, 1, ((scan_in & 0x08) >> 3));
332                 }
333
334                 bit_count++;
335         }
336
337         if (!((ir_scan && (tap_get_end_state() == TAP_IRSHIFT)) ||
338                 (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT))))
339         {
340                 gw16012_data(0x0);
341                 if (ir_scan)
342                         tap_set_state(TAP_IRPAUSE);
343                 else
344                         tap_set_state(TAP_DRPAUSE);
345
346                 if (tap_get_state() != tap_get_end_state())
347                         gw16012_state_move();
348         }
349 }
350
351 static int gw16012_execute_queue(void)
352 {
353         jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
354         int scan_size;
355         enum scan_type type;
356         u8 *buffer;
357         int retval;
358
359         /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
360          * that wasn't handled by a caller-provided error handler
361          */
362         retval = ERROR_OK;
363
364         while (cmd)
365         {
366                 switch (cmd->type)
367                 {
368                         case JTAG_END_STATE:
369 #ifdef _DEBUG_JTAG_IO_
370                                 LOG_DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
371 #endif
372                                 if (cmd->cmd.end_state->end_state != TAP_INVALID)
373                                         gw16012_end_state(cmd->cmd.end_state->end_state);
374                                 break;
375                         case JTAG_RESET:
376 #ifdef _DEBUG_JTAG_IO_
377                                 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
378 #endif
379                                 if (cmd->cmd.reset->trst == 1)
380                                 {
381                                         tap_set_state(TAP_RESET);
382                                 }
383                                 gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
384                                 break;
385                         case JTAG_RUNTEST:
386 #ifdef _DEBUG_JTAG_IO_
387                                 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
388 #endif
389                                 if (cmd->cmd.runtest->end_state != TAP_INVALID)
390                                         gw16012_end_state(cmd->cmd.runtest->end_state);
391                                 gw16012_runtest(cmd->cmd.runtest->num_cycles);
392                                 break;
393                         case JTAG_STATEMOVE:
394 #ifdef _DEBUG_JTAG_IO_
395                                 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
396 #endif
397                                 if (cmd->cmd.statemove->end_state != TAP_INVALID)
398                                         gw16012_end_state(cmd->cmd.statemove->end_state);
399                                 gw16012_state_move();
400                                 break;
401                         case JTAG_PATHMOVE:
402 #ifdef _DEBUG_JTAG_IO_
403                                 LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
404 #endif
405                                 gw16012_path_move(cmd->cmd.pathmove);
406                                 break;
407                         case JTAG_SCAN:
408                                 if (cmd->cmd.scan->end_state != TAP_INVALID)
409                                         gw16012_end_state(cmd->cmd.scan->end_state);
410                                 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
411                                 type = jtag_scan_type(cmd->cmd.scan);
412 #ifdef _DEBUG_JTAG_IO_
413                                 LOG_DEBUG("%s scan (%i) %i bit end in %i", (cmd->cmd.scan->ir_scan) ? "ir" : "dr",
414                                         type, scan_size, cmd->cmd.scan->end_state);
415 #endif
416                                 gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
417                                 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
418                                         retval = ERROR_JTAG_QUEUE_FAILED;
419                                 if (buffer)
420                                         free(buffer);
421                                 break;
422                         case JTAG_SLEEP:
423 #ifdef _DEBUG_JTAG_IO_
424                                 LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
425 #endif
426                                 jtag_sleep(cmd->cmd.sleep->us);
427                                 break;
428                         default:
429                                 LOG_ERROR("BUG: unknown JTAG command type encountered");
430                                 exit(-1);
431                 }
432                 cmd = cmd->next;
433         }
434
435         return retval;
436 }
437
438 #if PARPORT_USE_GIVEIO == 1
439 static int gw16012_get_giveio_access()
440 {
441         HANDLE h;
442         OSVERSIONINFO version;
443
444         version.dwOSVersionInfoSize = sizeof version;
445         if (!GetVersionEx( &version )) {
446                 errno = EINVAL;
447                 return -1;
448         }
449         if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
450                 return 0;
451
452         h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
453         if (h == INVALID_HANDLE_VALUE) {
454                 errno = ENODEV;
455                 return -1;
456         }
457
458         CloseHandle( h );
459
460         return 0;
461 }
462 #endif
463
464 static int gw16012_init(void)
465 {
466 #if PARPORT_USE_PPDEV == 1
467         char buffer[256];
468         int i = 0;
469 #endif
470         u8 status_port;
471
472 #if PARPORT_USE_PPDEV == 1
473         if (device_handle>0)
474         {
475                 LOG_ERROR("device is already opened");
476                 return ERROR_JTAG_INIT_FAILED;
477         }
478
479 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
480         LOG_DEBUG("opening /dev/ppi%d...", gw16012_port);
481
482         snprintf(buffer, 256, "/dev/ppi%d", gw16012_port);
483         device_handle = open(buffer, O_WRONLY);
484 #else
485         LOG_DEBUG("opening /dev/parport%d...", gw16012_port);
486
487         snprintf(buffer, 256, "/dev/parport%d", gw16012_port);
488         device_handle = open(buffer, O_WRONLY);
489 #endif
490         if (device_handle<0)
491         {
492                 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
493                 return ERROR_JTAG_INIT_FAILED;
494         }
495
496         LOG_DEBUG("...open");
497
498 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
499         i=ioctl(device_handle, PPCLAIM);
500         if (i<0)
501         {
502                 LOG_ERROR("cannot claim device");
503                 return ERROR_JTAG_INIT_FAILED;
504         }
505
506         i = PARPORT_MODE_COMPAT;
507         i= ioctl(device_handle, PPSETMODE, & i);
508         if (i<0)
509         {
510                 LOG_ERROR(" cannot set compatible mode to device");
511                 return ERROR_JTAG_INIT_FAILED;
512         }
513
514         i = IEEE1284_MODE_COMPAT;
515         i = ioctl(device_handle, PPNEGOT, & i);
516         if (i<0)
517         {
518                 LOG_ERROR("cannot set compatible 1284 mode to device");
519                 return ERROR_JTAG_INIT_FAILED;
520         }
521 #endif
522 #else
523         if (gw16012_port == 0)
524         {
525                 gw16012_port = 0x378;
526                 LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
527         }
528
529         LOG_DEBUG("requesting privileges for parallel port 0x%lx...", (long unsigned)(gw16012_port) );
530 #if PARPORT_USE_GIVEIO == 1
531         if (gw16012_get_giveio_access() != 0)
532 #else /* PARPORT_USE_GIVEIO */
533         if (ioperm(gw16012_port, 3, 1) != 0)
534 #endif /* PARPORT_USE_GIVEIO */
535         {
536                 LOG_ERROR("missing privileges for direct i/o");
537                 return ERROR_JTAG_INIT_FAILED;
538         }
539         LOG_DEBUG("...privileges granted");
540
541         /* make sure parallel port is in right mode (clear tristate and interrupt */
542 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
543         outb(gw16012_port + 2, 0x0);
544 #else
545         outb(0x0, gw16012_port + 2);
546 #endif
547 #endif /* PARPORT_USE_PPDEV */
548
549         gw16012_input(&status_port);
550         gw16012_msb = (status_port & 0x80) ^ 0x80;
551
552         gw16012_speed(jtag_speed);
553         gw16012_reset(0, 0);
554
555         return ERROR_OK;
556 }
557
558 static int gw16012_quit(void)
559 {
560
561         return ERROR_OK;
562 }
563
564 static int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
565 {
566         if (argc == 0)
567                 return ERROR_OK;
568
569         /* only if the port wasn't overwritten by cmdline */
570         if (gw16012_port == 0)
571                 gw16012_port = strtoul(args[0], NULL, 0);
572
573         return ERROR_OK;
574 }