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