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