]> git.sur5r.net Git - openocd/blobdiff - src/jtag/gw16012.c
code to be used in upcoming minidriver work.
[openocd] / src / jtag / gw16012.c
index 6210a52c48821527901685a16ced649d48c766e5..c634df3199476a064f29d38f130c0c68b678747f 100644 (file)
 
 #include "jtag.h"
 
-/* system includes */
+#if 1
+#define _DEBUG_GW16012_IO_
+#endif
 
 /* system includes */
 // -ino: 060521-1036
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 
 #include <sys/types.h>
 #include <machine/sysarch.h>
 
 #else
 
-#ifndef _WIN32
-#include <sys/io.h>
-#else
+#ifdef _WIN32
 #include "errno.h"
 #endif /* _WIN32 */
 
-#endif /* __FreeBSD__ */
+#endif /* __FreeBSD__, __FreeBSD_kernel__ */
 
 #include <string.h>
 #include <stdlib.h>
@@ -54,7 +54,7 @@
 #include <time.h>
 
 #if PARPORT_USE_PPDEV == 1
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 #include <dev/ppbus/ppi.h>
 #include <dev/ppbus/ppbconf.h>
 #define PPRSTATUS      PPIGSTATUS
 #endif
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#else /* not PARPORT_USE_PPDEV */
+#ifndef _WIN32
+#include <sys/io.h>
+#endif
 #endif
 
 #if PARPORT_USE_GIVEIO == 1
@@ -78,7 +82,7 @@
 #include "log.h"
 
 /* configuration */
-unsigned long gw16012_port;
+u16 gw16012_port;
 
 /* interface variables
  */
@@ -103,8 +107,6 @@ jtag_interface_t gw16012_interface =
        
        .execute_queue = gw16012_execute_queue,
 
-       .support_pathmove = 0,
-
        .speed = gw16012_speed, 
        .register_commands = gw16012_register_commands,
        .init = gw16012_init,
@@ -123,11 +125,15 @@ void gw16012_data(u8 value)
 {
        value = (value & 0x7f) | gw16012_msb;
        gw16012_msb ^= 0x80; /* toggle MSB */
+
+#ifdef _DEBUG_GW16012_IO_
+       DEBUG("%2.2x", value);
+#endif
        
        #if PARPORT_USE_PPDEV == 1
                ioctl(device_handle, PPWDATA, &value);
        #else
-               #ifdef __FreeBSD__
+               #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
                        outb(gw16012_port, value);
                #else
                        outb(value, gw16012_port);
@@ -141,10 +147,14 @@ void gw16012_control(u8 value)
        {
                gw16012_control_value = value;
 
+#ifdef _DEBUG_GW16012_IO_
+               DEBUG("%2.2x", gw16012_control_value);
+#endif
+
                #if PARPORT_USE_PPDEV == 1
                        ioctl(device_handle, PPWCONTROL, &gw16012_control_value);
                #else
-                       #ifdef __FreeBSD__
+                       #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
                                outb(gw16012_port + 2, gw16012_control_value);
                        #else
                                outb(gw16012_control_value, gw16012_port + 2);
@@ -160,6 +170,10 @@ void gw16012_input(u8 *value)
        #else
                *value = inb(gw16012_port + 1);
        #endif
+
+#ifdef _DEBUG_GW16012_IO_
+       DEBUG("%2.2x", *value);
+#endif
 }
 
 /* (1) assert or (0) deassert reset lines */
@@ -211,6 +225,37 @@ void gw16012_state_move(void)
        cur_state = end_state;
 }
 
+void gw16012_path_move(pathmove_command_t *cmd)
+{
+       int num_states = cmd->num_states;
+       int state_count;
+
+       state_count = 0;
+       while (num_states)
+       {
+               gw16012_control(0x0); /* single-bit mode */
+               if (tap_transitions[cur_state].low == cmd->path[state_count])
+               {
+                       gw16012_data(0x0); /* TCK cycle with TMS low */
+               }
+               else if (tap_transitions[cur_state].high == cmd->path[state_count])
+               {
+                       gw16012_data(0x2); /* TCK cycle with TMS high */
+               }
+               else
+               {
+                       ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);
+                       exit(-1);
+               }
+               
+               cur_state = cmd->path[state_count];
+               state_count++;
+               num_states--;
+       }
+       
+       end_state = cur_state;
+}
+
 void gw16012_runtest(int num_cycles)
 {
        enum tap_state saved_end_state = end_state;
@@ -241,13 +286,17 @@ void gw16012_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
        enum tap_state saved_end_state = end_state;
        u8 scan_out, scan_in;
 
-       if (ir_scan)
-               gw16012_end_state(TAP_SI);
-       else
-               gw16012_end_state(TAP_SD);
+       /* only if we're not already in the correct Shift state */
+       if (!((!ir_scan && (cur_state == TAP_SD)) || (ir_scan && (cur_state == TAP_SI))))
+       {
+               if (ir_scan)
+                       gw16012_end_state(TAP_SI);
+               else
+                       gw16012_end_state(TAP_SD);
 
-       gw16012_state_move();
-       gw16012_end_state(saved_end_state);
+               gw16012_state_move();
+               gw16012_end_state(saved_end_state);
+       }
 
        while (type == SCAN_OUT && ((bits_left - 1) > 7))
        {
@@ -262,6 +311,9 @@ void gw16012_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
        while (bits_left-- > 0)
        {
                u8 tms = 0;
+               
+               scan_out = buf_get_u32(buffer, bit_count, 1);
+               
                if (bits_left == 0) /* last bit */
                {
                        if ((ir_scan && (end_state == TAP_SI))
@@ -274,14 +326,15 @@ void gw16012_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
                                tms = 2;
                        }
                }
-               
-               scan_out = buf_get_u32(buffer, bit_count, 1);
+
                gw16012_data(scan_out | tms);
+
                if (type != SCAN_OUT)
                {
                        gw16012_input(&scan_in);
                        buf_set_u32(buffer, bit_count, 1, ((scan_in & 0x08) >> 3));
-               }
+               }               
+
                bit_count++;
        }
 
@@ -305,6 +358,12 @@ int gw16012_execute_queue(void)
        int scan_size;
        enum scan_type type;
        u8 *buffer;
+       int retval;
+       
+       /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
+        * that wasn't handled by a caller-provided error handler
+        */ 
+       retval = ERROR_OK;
                
        while (cmd)
        {
@@ -343,6 +402,12 @@ int gw16012_execute_queue(void)
                                        gw16012_end_state(cmd->cmd.statemove->end_state);
                                gw16012_state_move();
                                break;
+                       case JTAG_PATHMOVE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+#endif
+                               gw16012_path_move(cmd->cmd.pathmove);
+                               break;
                        case JTAG_SCAN:
                                if (cmd->cmd.scan->end_state != -1)
                                        gw16012_end_state(cmd->cmd.scan->end_state);
@@ -354,13 +419,13 @@ int gw16012_execute_queue(void)
 #endif
                                gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
                                if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
-                                       return ERROR_JTAG_QUEUE_FAILED;
+                                       retval = ERROR_JTAG_QUEUE_FAILED;
                                if (buffer)
                                        free(buffer);
                                break;
                        case JTAG_SLEEP:
 #ifdef _DEBUG_JTAG_IO_
-                               DEBUG("sleep", cmd->cmd.sleep->us);
+                               DEBUG("sleep %i", cmd->cmd.sleep->us);
 #endif
                                jtag_sleep(cmd->cmd.sleep->us);
                                break;
@@ -371,7 +436,7 @@ int gw16012_execute_queue(void)
                cmd = cmd->next;
        }
        
-       return ERROR_OK;
+       return retval;
 }
 
 #if PARPORT_USE_GIVEIO == 1
@@ -405,7 +470,6 @@ int gw16012_init(void)
 #if PARPORT_USE_PPDEV == 1
        char buffer[256];
        int i = 0;
-       u8 control_port;
 #endif
        u8 status_port;
        
@@ -416,7 +480,7 @@ int gw16012_init(void)
                return ERROR_JTAG_INIT_FAILED;
        }
 
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
        DEBUG("opening /dev/ppi%d...", gw16012_port);
 
        snprintf(buffer, 256, "/dev/ppi%d", gw16012_port);
@@ -435,7 +499,7 @@ int gw16012_init(void)
 
        DEBUG("...open");
 
-#ifndef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
        i=ioctl(device_handle, PPCLAIM);
        if (i<0)
        {
@@ -466,7 +530,7 @@ int gw16012_init(void)
                WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
        }
        
-       DEBUG("requesting privileges for parallel port 0x%x...", gw16012_port);
+       DEBUG("requesting privileges for parallel port 0x%lx...", gw16012_port);
 #if PARPORT_USE_GIVEIO == 1
        if (gw16012_get_giveio_access() != 0)
 #else /* PARPORT_USE_GIVEIO */
@@ -477,6 +541,13 @@ int gw16012_init(void)
                return ERROR_JTAG_INIT_FAILED;
        }
        DEBUG("...privileges granted");
+
+       /* make sure parallel port is in right mode (clear tristate and interrupt */
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+       outb(gw16012_port + 2, 0x0);
+#else
+       outb(0x0, gw16012_port + 2);
+#endif
 #endif /* PARPORT_USE_PPDEV */
        
        gw16012_input(&status_port);