Remove whitespace that occurs after '('.
[fw/openocd] / src / jtag / parport.c
index a46d611fd9ea0319e5deab7365a65cb8963a9f33..ec6a862f6d68151201d4613e83d5e6e6563800f3 100644 (file)
@@ -2,6 +2,9 @@
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
 #include "config.h"
 #endif
 
-#include "replacements.h"
-
-#include "jtag.h"
+#include "interface.h"
 #include "bitbang.h"
 
-/* system includes */
-// -ino: 060521-1036
-#ifdef __FreeBSD__
-
-#include <sys/types.h>
+/* -ino: 060521-1036 */
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 #include <machine/sysarch.h>
 #include <machine/cpufunc.h>
 #define ioperm(startport,length,enable)\
   i386_set_ioperm((startport), (length), (enable))
-
-#else
-
-#ifndef _WIN32
-#include <sys/io.h>
-#else
-#include "errno.h"
-#endif /* _WIN32 */
-
 #endif /* __FreeBSD__ */
 
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.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
 #include <linux/parport.h>
 #include <linux/ppdev.h>
 #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
-#if IS_CYGWIN == 1
+#if PARPORT_USE_GIVEIO == 1 && IS_CYGWIN == 1
 #include <windows.h>
-#include <errno.h>
-#undef ERROR
-#endif
 #endif
 
-#include "log.h"
 
 /* parallel port cable description
  */
 typedef struct cable_s
 {
        char* name;
-       u8 TDO_MASK;    /* status port bit containing current TDO value */
-       u8 TRST_MASK;   /* data port bit for TRST */
-       u8 TMS_MASK;    /* data port bit for TMS */
-       u8 TCK_MASK;    /* data port bit for TCK */
-       u8 TDI_MASK;    /* data port bit for TDI */
-       u8 SRST_MASK;   /* data port bit for SRST */
-       u8 OUTPUT_INVERT;       /* data port bits that should be inverted */
-       u8 INPUT_INVERT;        /* status port that should be inverted */
-       u8 PORT_INIT;   /* initialize data port with this value */
+       uint8_t TDO_MASK;       /* status port bit containing current TDO value */
+       uint8_t TRST_MASK;      /* data port bit for TRST */
+       uint8_t TMS_MASK;       /* data port bit for TMS */
+       uint8_t TCK_MASK;       /* data port bit for TCK */
+       uint8_t TDI_MASK;       /* data port bit for TDI */
+       uint8_t SRST_MASK;      /* data port bit for SRST */
+       uint8_t OUTPUT_INVERT;  /* data port bits that should be inverted */
+       uint8_t INPUT_INVERT;   /* status port that should be inverted */
+       uint8_t PORT_INIT;      /* initialize data port with this value */
+       uint8_t PORT_EXIT;      /* de-initialize data port with this value */
+       uint8_t LED_MASK;       /* data port bit for LED */
 } cable_t;
 
-cable_t cables[] = 
-{      
-       /* name                                 tdo   trst  tms   tck   tdi   srst  o_inv i_inv init */
-       { "wiggler",                    0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80 },
-       { "wiggler_ntrst_inverted",     0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80 },
-       { "old_amt_wiggler",    0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80 },
-       { "chameleon",                  0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00 },
-       { "dlc5",                               0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10 },
-       { "triton",                             0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00 },
-       { "lattice",                    0x40, 0x10, 0x04, 0x02, 0x01, 0x08, 0x00, 0x00, 0x18 },
-       { "flashlink",                  0x20, 0x10, 0x02, 0x01, 0x04, 0x20, 0x30, 0x20, 0x00 },
-       { NULL,                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+static cable_t cables[] =
+{
+       /* name                                 tdo   trst  tms   tck   tdi   srst  o_inv i_inv init  exit  led */
+       { "wiggler",                    0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x80, 0x00 },
+       { "wiggler2",                   0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x00, 0x20 },
+       { "wiggler_ntrst_inverted",
+                                                       0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80, 0x80, 0x00 },
+       { "old_amt_wiggler",    0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80, 0x80, 0x00 },
+       { "arm-jtag",                   0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x01, 0x80, 0x80, 0x80, 0x00 },
+       { "chameleon",                  0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
+       { "dlc5",                               0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00 },
+       { "triton",                             0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
+       { "lattice",                    0x40, 0x10, 0x04, 0x02, 0x01, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00 },
+       { "flashlink",                  0x20, 0x10, 0x02, 0x01, 0x04, 0x20, 0x30, 0x20, 0x00, 0x00, 0x00 },
+/* Altium Universal JTAG cable. Set the cable to Xilinx Mode and wire to target as follows:
+       HARD TCK - Target TCK
+       HARD TMS - Target TMS
+       HARD TDI - Target TDI
+       HARD TDO - Target TDO
+       SOFT TCK - Target TRST
+       SOFT TDI - Target SRST
+*/
+       { "altium",                     0x10, 0x20, 0x04, 0x02, 0x01, 0x80, 0x00, 0x00, 0x10, 0x00, 0x08 },
+       { NULL,                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
 };
 
 /* configuration */
-char* parport_cable;
-unsigned long parport_port;
+static char* parport_cable = NULL;
+static uint16_t parport_port;
+static int parport_exit = 0;
 
 /* interface variables
  */
 static cable_t* cable;
-static u8 dataport_value = 0x0;
+static uint8_t dataport_value = 0x0;
 
 #if PARPORT_USE_PPDEV == 1
 static int device_handle;
@@ -122,44 +120,45 @@ static unsigned long statusport;
 
 /* low level command set
  */
-int parport_read(void);
-void parport_write(int tck, int tms, int tdi);
-void parport_reset(int trst, int srst);
+static int parport_read(void);
+static void parport_write(int tck, int tms, int tdi);
+static void parport_reset(int trst, int srst);
+static void parport_led(int on);
 
-int parport_speed(int speed);
-int parport_register_commands(struct command_context_s *cmd_ctx);
-int parport_init(void);
-int parport_quit(void);
+static int parport_speed(int speed);
+static int parport_register_commands(struct command_context_s *cmd_ctx);
+static int parport_init(void);
+static int parport_quit(void);
 
 /* interface commands */
-int parport_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int parport_handle_parport_cable_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int parport_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int parport_handle_parport_cable_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int parport_handle_write_on_exit_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
-jtag_interface_t parport_interface = 
+jtag_interface_t parport_interface =
 {
        .name = "parport",
-       
-       .execute_queue = bitbang_execute_queue,
 
-       .support_pathmove = 1,
+       .execute_queue = bitbang_execute_queue,
 
-       .speed = parport_speed, 
+       .speed = parport_speed,
        .register_commands = parport_register_commands,
        .init = parport_init,
        .quit = parport_quit,
 };
 
-bitbang_interface_t parport_bitbang =
+static bitbang_interface_t parport_bitbang =
 {
        .read = parport_read,
        .write = parport_write,
-       .reset = parport_reset
+       .reset = parport_reset,
+       .blink = parport_led
 };
 
-int parport_read(void)
+static int parport_read(void)
 {
        int data = 0;
-       
+
 #if PARPORT_USE_PPDEV == 1
        ioctl(device_handle, PPRSTATUS, & data);
 #else
@@ -172,45 +171,49 @@ int parport_read(void)
                return 0;
 }
 
-void parport_write(int tck, int tms, int tdi)
+static __inline__ void parport_write_data(void)
 {
-       u8 output;
-       int i = jtag_speed + 1;
-       
+       uint8_t output;
+       output = dataport_value ^ cable->OUTPUT_INVERT;
+
+#if PARPORT_USE_PPDEV == 1
+       ioctl(device_handle, PPWDATA, &output);
+#else
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+       outb(dataport, output);
+#else
+       outb(output, dataport);
+#endif
+#endif
+}
+
+static void parport_write(int tck, int tms, int tdi)
+{
+       int i = jtag_get_speed() + 1;
+
        if (tck)
                dataport_value |= cable->TCK_MASK;
        else
                dataport_value &= ~cable->TCK_MASK;
-       
+
        if (tms)
                dataport_value |= cable->TMS_MASK;
        else
                dataport_value &= ~cable->TMS_MASK;
-       
+
        if (tdi)
                dataport_value |= cable->TDI_MASK;
        else
                dataport_value &= ~cable->TDI_MASK;
-               
-       output = dataport_value ^ cable->OUTPUT_INVERT;
 
        while (i-- > 0)
-#if PARPORT_USE_PPDEV == 1
-               ioctl(device_handle, PPWDATA, &output);
-#else
-#ifdef __FreeBSD__
-       outb(dataport, output);
-#else
-       outb(output, dataport);
-#endif
-#endif
+               parport_write_data();
 }
 
 /* (1) assert or (0) deassert reset lines */
-void parport_reset(int trst, int srst)
+static void parport_reset(int trst, int srst)
 {
-       u8 output;
-       DEBUG("trst: %i, srst: %i", trst, srst);
+       LOG_DEBUG("trst: %i, srst: %i", trst, srst);
 
        if (trst == 0)
                dataport_value |= cable->TRST_MASK;
@@ -221,80 +224,80 @@ void parport_reset(int trst, int srst)
                dataport_value |= cable->SRST_MASK;
        else if (srst == 1)
                dataport_value &= ~cable->SRST_MASK;
-       
-       output = dataport_value ^ cable->OUTPUT_INVERT;
-       
-#if PARPORT_USE_PPDEV == 1
-       ioctl(device_handle, PPWDATA, &output);
-#else
-#ifdef __FreeBSD__
-       outb(dataport, output);
-#else
-       outb(output, dataport);
-#endif
-#endif
 
+       parport_write_data();
 }
 
-int parport_speed(int speed)
+/* turn LED on parport adapter on (1) or off (0) */
+static void parport_led(int on)
+{
+       if (on)
+               dataport_value |= cable->LED_MASK;
+       else
+               dataport_value &= ~cable->LED_MASK;
+
+       parport_write_data();
+}
+
+static int parport_speed(int speed)
 {
-       jtag_speed = speed;
-       
        return ERROR_OK;
 }
 
-int parport_register_commands(struct command_context_s *cmd_ctx)
+static int parport_register_commands(struct command_context_s *cmd_ctx)
 {
        register_command(cmd_ctx, NULL, "parport_port", parport_handle_parport_port_command,
-               COMMAND_CONFIG, NULL);
+               COMMAND_CONFIG, "either the address of the I/O port or the number of the \91/dev/parport\92 device");
        register_command(cmd_ctx, NULL, "parport_cable", parport_handle_parport_cable_command,
-               COMMAND_CONFIG, NULL);
+               COMMAND_CONFIG, "the layout of the parallel port cable used to connect to the target");
+       register_command(cmd_ctx, NULL, "parport_write_on_exit", parport_handle_write_on_exit_command,
+               COMMAND_CONFIG, "configure the parallel driver to write a known value to the parallel interface");
 
        return ERROR_OK;
 }
 
 #if PARPORT_USE_GIVEIO == 1
-int parport_get_giveio_access()
+static int parport_get_giveio_access(void)
 {
-    HANDLE h;
-    OSVERSIONINFO version;
-
-    version.dwOSVersionInfoSize = sizeof version;
-    if (!GetVersionEx( &version )) {
-        errno = EINVAL;
-        return -1;
-    }
-    if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
-        return 0;
-
-    h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
-    if (h == INVALID_HANDLE_VALUE) {
-        errno = ENODEV;
-        return -1;
-    }
-
-    CloseHandle( h );
-
-    return 0;
+       HANDLE h;
+       OSVERSIONINFO version;
+
+       version.dwOSVersionInfoSize = sizeof version;
+       if (!GetVersionEx(&version )) {
+               errno = EINVAL;
+               return -1;
+       }
+       if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
+               return 0;
+
+       h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+       if (h == INVALID_HANDLE_VALUE) {
+               errno = ENODEV;
+               return -1;
+       }
+
+       CloseHandle(h );
+
+       return 0;
 }
 #endif
 
-int parport_init(void)
+static int parport_init(void)
 {
        cable_t *cur_cable;
 #if PARPORT_USE_PPDEV == 1
        char buffer[256];
        int i = 0;
 #endif
-       
+
        cur_cable = cables;
-       
+
        if ((parport_cable == NULL) || (parport_cable[0] == 0))
        {
                parport_cable = "wiggler";
-               WARNING("No parport cable specified, using default 'wiggler'");
+               LOG_WARNING("No parport cable specified, using default 'wiggler'");
        }
-       
+
        while (cur_cable->name)
        {
                if (strcmp(cur_cable->name, parport_cable) == 0)
@@ -307,122 +310,147 @@ int parport_init(void)
 
        if (!cable)
        {
-               ERROR("No matching cable found for %s", parport_cable);
+               LOG_ERROR("No matching cable found for %s", parport_cable);
                return ERROR_JTAG_INIT_FAILED;
        }
-       
+
        dataport_value = cable->PORT_INIT;
-       
+
 #if PARPORT_USE_PPDEV == 1
        if (device_handle > 0)
        {
-               ERROR("device is already opened");
+               LOG_ERROR("device is already opened");
                return ERROR_JTAG_INIT_FAILED;
        }
 
-#ifdef __FreeBSD__
-       DEBUG("opening /dev/ppi%d...", parport_port);
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+       LOG_DEBUG("opening /dev/ppi%d...", parport_port);
 
        snprintf(buffer, 256, "/dev/ppi%d", parport_port);
        device_handle = open(buffer, O_WRONLY);
-#else /* not __Free_BSD */
-       DEBUG("opening /dev/parport%d...", parport_port);
+#else /* not __FreeBSD__, __FreeBSD_kernel__ */
+       LOG_DEBUG("opening /dev/parport%d...", parport_port);
 
        snprintf(buffer, 256, "/dev/parport%d", parport_port);
        device_handle = open(buffer, O_WRONLY);
-#endif /* __FreeBSD__ */
+#endif /* __FreeBSD__, __FreeBSD_kernel__ */
 
        if (device_handle < 0)
        {
-               ERROR("cannot open device. check it exists and that user read and write rights are set");
+               LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       DEBUG("...open");
+       LOG_DEBUG("...open");
 
-#ifndef __FreeBSD__
-       i=ioctl(device_handle, PPCLAIM);
-       if (i<0)
+#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
+       i = ioctl(device_handle, PPCLAIM);
+       if (i < 0)
        {
-               ERROR("cannot claim device");
+               LOG_ERROR("cannot claim device");
                return ERROR_JTAG_INIT_FAILED;
        }
 
        i = PARPORT_MODE_COMPAT;
        i= ioctl(device_handle, PPSETMODE, & i);
-       if (i<0)
+       if (i < 0)
        {
-               ERROR(" cannot set compatible mode to device");
+               LOG_ERROR(" cannot set compatible mode to device");
                return ERROR_JTAG_INIT_FAILED;
        }
 
        i = IEEE1284_MODE_COMPAT;
        i = ioctl(device_handle, PPNEGOT, & i);
-       if (i<0)
+       if (i < 0)
        {
-               ERROR("cannot set compatible 1284 mode to device");
+               LOG_ERROR("cannot set compatible 1284 mode to device");
                return ERROR_JTAG_INIT_FAILED;
        }
-#endif /* not __Free_BSD__ */
+#endif /* not __FreeBSD__, __FreeBSD_kernel__ */
 
 #else /* not PARPORT_USE_PPDEV */
        if (parport_port == 0)
        {
                parport_port = 0x378;
-               WARNING("No parport port specified, using default '0x378' (LPT1)");
+               LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
        }
-       
+
        dataport = parport_port;
        statusport = parport_port + 1;
-       
-       DEBUG("requesting privileges for parallel port 0x%lx...", dataport);
+
+       LOG_DEBUG("requesting privileges for parallel port 0x%lx...", dataport);
 #if PARPORT_USE_GIVEIO == 1
        if (parport_get_giveio_access() != 0)
 #else /* PARPORT_USE_GIVEIO */
        if (ioperm(dataport, 3, 1) != 0)
 #endif /* PARPORT_USE_GIVEIO */
        {
-               ERROR("missing privileges for direct i/o");
+               LOG_ERROR("missing privileges for direct i/o");
                return ERROR_JTAG_INIT_FAILED;
        }
-       DEBUG("...privileges granted");
-       
+       LOG_DEBUG("...privileges granted");
+
        /* make sure parallel port is in right mode (clear tristate and interrupt */
-       #ifdef __FreeBSD__
+       #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
                outb(parport_port + 2, 0x0);
        #else
                outb(0x0, parport_port + 2);
        #endif
-       
+
 #endif /* PARPORT_USE_PPDEV */
-       
+
        parport_reset(0, 0);
        parport_write(0, 0, 0);
+       parport_led(1);
 
-       bitbang_interface = &parport_bitbang;   
+       bitbang_interface = &parport_bitbang;
 
        return ERROR_OK;
 }
 
-int parport_quit(void)
+static int parport_quit(void)
 {
+       parport_led(0);
+
+       if (parport_exit)
+       {
+               dataport_value = cable->PORT_EXIT;
+               parport_write_data();
+       }
+
+       if (parport_cable)
+       {
+               free(parport_cable);
+               parport_cable = NULL;
+       }
 
        return ERROR_OK;
 }
 
-int parport_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int parport_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       if (argc == 0)
-               return ERROR_OK;
+       if (argc == 1)
+       {
+               /* only if the port wasn't overwritten by cmdline */
+               if (parport_port == 0)
+               {
+                       int retval = parse_u16(args[0], &parport_port);
+                       if (ERROR_OK != retval)
+                               return retval;
+               }
+               else
+               {
+                       LOG_ERROR("The parport port was already configured!");
+                       return ERROR_FAIL;
+               }
+       }
 
-       /* only if the port wasn't overwritten by cmdline */
-       if (parport_port == 0)
-               parport_port = strtoul(args[0], NULL, 0);
+       command_print(cmd_ctx, "parport port = %u", parport_port);
 
        return ERROR_OK;
 }
 
-int parport_handle_parport_cable_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int parport_handle_parport_cable_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        if (argc == 0)
                return ERROR_OK;
@@ -436,3 +464,19 @@ int parport_handle_parport_cable_command(struct command_context_s *cmd_ctx, char
 
        return ERROR_OK;
 }
+
+static int parport_handle_write_on_exit_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc != 1)
+       {
+               command_print(cmd_ctx, "usage: parport_write_on_exit <on | off>");
+               return ERROR_OK;
+       }
+
+       if (strcmp(args[0], "on") == 0)
+               parport_exit = 1;
+       else if (strcmp(args[0], "off") == 0)
+               parport_exit = 0;
+
+       return ERROR_OK;
+}