Hi Urjtag authors!
Some time ago, while experimenting with UrJTAG, I wrote a driver to be able
to use the parallel port of my NetBSD machine with a ByteblasterMV cable.
The driver is called ppbusgpio.c, or just "gpio", because the ppbus under
NetBSD attaches 17 GPIO pins to control all parallel port lines via
/dev/gpio0.
Some days ago, while using UrJTAG again to unbrick my Allnet 6250, I adapted
my source to compile with the current r2012 revision.
You find a diff file on r2012 attached. It is complete, also in respect to
auto configuration (a new lowlevel driver "gpio" can be selected). I also
fixed some bugs with missing "(unsigned char)" casts, which cause error
messages since gcc 4.5.
It is tested and proven to work. Would be nice if you consider to include it
into future releases.
Regards,
--
Frank Wille
--- urjtag/configure.ac.orig 2011-11-19 20:20:43.000000000 +0100
+++ urjtag/configure.ac 2011-11-19 20:25:16.000000000 +0100
@@ -149,6 +149,7 @@
AC_CHECK_HEADERS([linux/ppdev.h], [HAVE_LINUX_PPDEV_H="yes"])
AC_CHECK_HEADERS([dev/ppbus/ppi.h], [HAVE_DEV_PPBUS_PPI_H="yes"])
+AC_CHECK_HEADERS([sys/gpio.h], [HAVE_SYS_GPIO_H="yes"])
AC_CHECK_HEADERS(m4_flatten([
wchar.h
windows.h
@@ -685,6 +686,7 @@
ftd2xx
ppdev
ppi
+ gpio
],[
],[
# automatically disable lowlevel drivers when a required feature is not
available
@@ -700,6 +702,9 @@
AS_IF([test "x$HAVE_DEV_PPBUS_PPI_H" != "xyes"], [
drivers=`echo ${drivers} | $SED -e "s/ppi//"`
])
+ AS_IF([test "x$HAVE_SYS_GPIO_H" != "xyes"], [
+ drivers=`echo ${drivers} | $SED -e "s/gpio//"`
+ ])
AS_IF([test "x$HAVE_IOPERM" != "xyes" -a "x$HAVE_I386_SET_IOPERM" !=
"xyes" -a "x$HAVE_INPOUTXX" != "xyes" ], [
drivers=`echo ${drivers} | $SED -e "s/direct//"`
])
--- urjtag/include/urjtag/parport.h.orig 2011-11-19 20:35:12.000000000
+0100
+++ urjtag/include/urjtag/parport.h 2011-11-19 20:35:40.000000000 +0100
@@ -36,6 +36,7 @@
URJ_CABLE_PARPORT_DEV_PARALLEL,
URJ_CABLE_PARPORT_DEV_PPDEV,
URJ_CABLE_PARPORT_DEV_PPI,
+ URJ_CABLE_PARPORT_DEV_GPIO,
URJ_CABLE_PARPORT_N_DEVS,
}
urj_cable_parport_devtype_t;
--- urjtag/src/tap/parport/ppbusgpio.c.orig 2011-11-20 12:33:26.000000000
+0100
+++ urjtag/src/tap/parport/ppbusgpio.c 2011-11-20 12:55:31.000000000 +0100
@@ -0,0 +1,277 @@
+/*
+ * $Id: $
+ *
+ * NetBSD ppbus/gpio Driver
+ * Copyright (C) 2011 Frank Wille
+ *
+ * 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 (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by Frank Wille <[email protected]>, 2011.
+ *
+ */
+
+#include <sysdep.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/gpio.h>
+#include <sys/ioctl.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <urjtag/error.h>
+#include <urjtag/log.h>
+#include <urjtag/parport.h>
+#include <urjtag/cable.h>
+#include "../parport.h"
+
+static port_node_t *ports = NULL; /* ppi parallel ports */
+
+typedef struct {
+ char *portname;
+ int fd;
+ uint8_t data, stat, ctrl;
+} gpio_params_t;
+
+static urj_parport_t *
+gpio_parport_alloc (const char *port)
+{
+ gpio_params_t *params = malloc (sizeof *params);
+ char *portname = strdup (port);
+ urj_parport_t *parport = malloc (sizeof *parport);
+ port_node_t *node = malloc (sizeof *node);
+
+ if (!node || !parport || !params || !portname) {
+ free (node);
+ free (parport);
+ free (params);
+ free (portname);
+ urj_error_set (URJ_ERROR_OUT_OF_MEMORY,
+ "malloc(%zd)/strdup(%s)/malloc(%zd)/malloc(%zd) fails",
+ sizeof *params, port, sizeof *parport, sizeof *node);
+ return NULL;
+ }
+
+ params->portname = portname;
+ params->fd = -1;
+
+ parport->params = params;
+ parport->driver = &urj_tap_parport_gpio_parport_driver;
+ parport->cable = NULL;
+
+ node->port = parport;
+ node->next = ports;
+
+ ports = node;
+
+ return parport;
+}
+
+static void
+gpio_parport_free (urj_parport_t *port)
+{
+ port_node_t **prev;
+
+ for (prev = &ports; *prev; prev = &((*prev)->next))
+ if ((*prev)->port == port)
+ break;
+
+ if (*prev) {
+ port_node_t *pn = *prev;
+ *prev = pn->next;
+ free (pn);
+ }
+
+ free (((gpio_params_t *) port->params)->portname);
+ free (port->params);
+ free (port);
+}
+
+static urj_parport_t *
+gpio_connect (const char *devname)
+{
+ port_node_t *pn;
+ urj_parport_t *parport;
+
+ for (pn = ports; pn; pn = pn->next)
+ if (strcmp (pn->port->params, devname) == 0)
+ {
+ urj_log (URJ_LOG_LEVEL_NORMAL,
+ _("Disconnecting %s from gpio port %s\n"),
+ _(pn->port->cable->driver->description), devname);
+ pn->port->cable->driver->disconnect (pn->port->cable);
+ break;
+ }
+
+ urj_log (URJ_LOG_LEVEL_NORMAL, _("Initializing gpio port %s\n"), devname);
+
+ parport = gpio_parport_alloc (devname);
+ if (!parport)
+ return NULL;
+
+ return parport;
+}
+
+static int
+gpio_open (urj_parport_t *parport)
+{
+ gpio_params_t *p = parport->params;
+ struct gpio_req req;
+ int pin;
+
+ p->fd = open (p->portname, O_RDWR);
+ if (p->fd < 0) {
+ urj_error_IO_set ("Cannot open(%s)", p->portname);
+ return URJ_STATUS_FAIL;
+ }
+
+ /* Initialize all GPIO pins with 0 */
+ memset(&req, 0, sizeof(req));
+ req.gp_value = GPIO_PIN_LOW;
+ for (pin = 0; pin < 17; pin++) {
+ req.gp_pin = pin;
+ if (ioctl(p->fd, GPIOWRITE, &req) == -1) {
+ close(p->fd);
+ p->fd = -1;
+ return URJ_STATUS_FAIL;
+ }
+ }
+ p->data = p->stat = p->ctrl = 0;
+
+ return URJ_STATUS_OK;
+}
+
+static int
+gpio_close (urj_parport_t *parport)
+{
+ int r = URJ_STATUS_OK;
+ gpio_params_t *p = parport->params;
+
+ if (close (p->fd) != 0) {
+ urj_error_IO_set ("Cannot close(%d)", p->fd);
+ return URJ_STATUS_FAIL;
+ }
+
+ p->fd = -1;
+ return r;
+}
+
+static int
+gpio_set_data (urj_parport_t *parport, unsigned char data)
+{
+ gpio_params_t *p = parport->params;
+ struct gpio_req req;
+ uint8_t changed, mask;
+ int i;
+
+ memset(&req, 0, sizeof(req));
+
+ if ((changed = data ^ p->data)) {
+ for (mask = 1, i = 1; i <= 8; mask <<= 1, i++) {
+ if ((changed & mask) != 0) {
+ req.gp_pin = i;
+ req.gp_value = (data & mask) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
+ if (ioctl(p->fd, GPIOWRITE, &req) == -1)
+ return URJ_STATUS_FAIL;
+ }
+ }
+ p->data = data;
+ }
+
+ return URJ_STATUS_OK;
+}
+
+static int
+gpio_get_data (urj_parport_t *parport)
+{
+ gpio_params_t *p = parport->params;
+ struct gpio_req req;
+ int d, i, mask;
+
+ memset(&req, 0, sizeof(req));
+
+ for (d = 0, mask = 1, i = 1; i <= 8; mask <<= 1, i++) {
+ req.gp_pin = i;
+ if (ioctl( p->fd, GPIOREAD, &req ) == -1)
+ return -1;
+ if (req.gp_value == GPIO_PIN_HIGH)
+ d |= mask;
+ }
+ p->data = d;
+
+ return d;
+}
+
+static int
+gpio_get_status (urj_parport_t *parport)
+{
+ gpio_params_t *p = parport->params;
+ struct gpio_req req;
+ int d, i, mask;
+ int pins[8] = { 0, 0, 0, 14, 12, 11, 9, 10 };
+
+ memset(&req, 0, sizeof(req));
+
+ for (d = 0, mask = (1<<3), i = 3; i < 8; mask <<= 1, i++) {
+ req.gp_pin = pins[i];
+ if (ioctl( p->fd, GPIOREAD, &req ) == -1)
+ return -1;
+ if (req.gp_value == GPIO_PIN_HIGH)
+ d |= mask;
+ }
+ p->stat = d;
+
+ return d;
+}
+
+static int
+gpio_set_control (urj_parport_t *parport, unsigned char data)
+{
+ gpio_params_t *p = parport->params;
+ struct gpio_req req;
+ unsigned char changed, mask;
+ int i;
+ int pins[4] = { 0, 13, 15, 16 };
+
+ memset(&req, 0, sizeof(req));
+
+ if ((changed = data ^ p->ctrl)) {
+ for (mask = 1, i = 0; i < 4; mask <<= 1, i++) {
+ if ((changed & mask) != 0) {
+ req.gp_pin = pins[i];
+ req.gp_value = (data & mask) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
+ if (ioctl( p->fd, GPIOWRITE, &req ) == -1)
+ return URJ_STATUS_FAIL;
+ }
+ }
+ p->ctrl = data;
+ }
+
+ return URJ_STATUS_OK;
+}
+
+const urj_parport_driver_t urj_tap_parport_gpio_parport_driver = {
+ URJ_CABLE_PARPORT_DEV_GPIO,
+ gpio_connect,
+ gpio_parport_free,
+ gpio_open,
+ gpio_close,
+ gpio_set_data,
+ gpio_get_data,
+ gpio_get_status,
+ gpio_set_control
+};
--- urjtag/src/tap/cable/generic_parport.c.orig 2011-11-19 20:38:06.000000000
+0100
+++ urjtag/src/tap/cable/generic_parport.c 2011-11-19 20:41:46.000000000
+0100
@@ -124,12 +124,18 @@
#if HAVE_DEV_PPBUS_PPI_H
" or: cable %s ppi PPIDEV\n"
#endif
+#if HAVE_SYS_GPIO_H
+ " or: cable %s gpio GPIODEV\n"
+#endif
"\n" "PORTADDR parallel port address (e.g. 0x378)\n"
#if ENABLE_LOWLEVEL_PPDEV
"PPDEV ppdev device (e.g. /dev/parport0)\n"
#endif
#if HAVE_DEV_PPBUS_PPI_H
- "PPIDEF ppi device (e.g. /dev/ppi0)\n"
+ "PPIDEV ppi device (e.g. /dev/ppi0)\n"
+#endif
+#if HAVE_SYS_GPIO_H
+ "GPIODEV gpio device (e.g. /dev/gpio0)\n"
#endif
"\n"),
#if ENABLE_LOWLEVEL_PPDEV
@@ -138,5 +144,8 @@
#if HAVE_DEV_PPBUS_PPI_H
cablename,
#endif
+#if HAVE_SYS_GPIO_H
+ cablename,
+#endif
cablename);
}
--- urjtag/src/tap/cable/wiggler.c.orig 2011-11-19 20:41:59.000000000 +0100
+++ urjtag/src/tap/cable/wiggler.c 2011-11-19 20:45:53.000000000 +0100
@@ -397,12 +397,18 @@
#if HAVE_DEV_PPBUS_PPI_H
" or: cable %s ppi PPIDEV [TDO,TRST,TDI,TCK,TMS,SRESET]\n"
#endif
+#if HAVE_SYS_GPIO_H
+ " or: cable %s gpio GPIODEV [TDO,TRST,TDI,TCK,TMS,SRESET]\n"
+#endif
"\n" "PORTADDR parallel port address (e.g. 0x378)\n"
#if ENABLE_LOWLEVEL_PPDEV
"PPDEV ppdev device (e.g. /dev/parport0)\n"
#endif
#if HAVE_DEV_PPBUS_PPI_H
- "PPIDEF ppi device (e.g. /dev/ppi0)\n"
+ "PPIDEV ppi device (e.g. /dev/ppi0)\n"
+#endif
+#if HAVE_SYS_GPIO_H
+ "GPIODEV ppi device (e.g. /dev/gpio0)\n"
#endif
"TDO, ... parallel port bit number, prepend '#' for
inversion\n"
" default is '%s'\n" "\n"),
@@ -412,6 +418,9 @@
#if HAVE_DEV_PPBUS_PPI_H
cablename,
#endif
+#if HAVE_SYS_GPIO_H
+ cablename,
+#endif
cablename, std_wgl_map);
}
--- urjtag/src/tap/Makefile.am.orig 2011-11-19 21:15:00.000000000 +0100
+++ urjtag/src/tap/Makefile.am 2011-11-20 12:34:06.000000000 +0100
@@ -182,6 +182,11 @@
parport/ppi.c
endif
+if ENABLE_LOWLEVEL_GPIO
+libtap_la_SOURCES += \
+ parport/ppbusgpio.c
+endif
+
if ENABLE_CABLE_EP9307
libtap_la_SOURCES += \
cable/vision_ep9307.c
--- urjtag/src/tap/parport.c.orig 2011-11-19 20:35:57.000000000 +0100
+++ urjtag/src/tap/parport.c 2011-11-19 20:36:39.000000000 +0100
@@ -81,6 +81,7 @@
case URJ_CABLE_PARPORT_DEV_PARALLEL: return "parallel";
case URJ_CABLE_PARPORT_DEV_PPDEV: return "ppdev";
case URJ_CABLE_PARPORT_DEV_PPI: return "ppi";
+ case URJ_CABLE_PARPORT_DEV_GPIO: return "gpio";
case URJ_CABLE_PARPORT_N_DEVS: return "#devs";
}
return "<unknown parport devtype>";
--- urjtag/src/tap/parport_list.h.orig 2011-11-19 20:36:01.000000000 +0100
+++ urjtag/src/tap/parport_list.h 2011-11-20 12:53:17.000000000 +0100
@@ -34,4 +34,8 @@
_URJ_LIST(ppi_parport)
#endif
+#ifdef ENABLE_LOWLEVEL_GPIO
+_URJ_LIST(gpio_parport)
+#endif
+
#undef _URJ_LIST
--- urjtag/src/tap/detect.c.orig 2011-11-20 12:45:49.000000000 +0100
+++ urjtag/src/tap/detect.c 2011-11-20 12:47:07.000000000 +0100
@@ -86,14 +86,14 @@
p = line;
/* skip whitespace */
- while (*p && isspace (*p))
+ while (*p && isspace ((unsigned char)*p))
p++;
/* remove ending whitespace */
s = strchr (p, '\0');
while (s != p)
{
- if (!isspace (*--s))
+ if (!isspace ((unsigned char)*--s))
break;
*s = '\0';
}
@@ -104,7 +104,7 @@
/* find end of field */
s = p;
- while (*s && !isspace (*s))
+ while (*s && !isspace ((unsigned char)*s))
s++;
if (*s)
*s++ = '\0';
@@ -122,7 +122,7 @@
p = s;
/* skip whitespace */
- while (*p && isspace (*p))
+ while (*p && isspace ((unsigned char)*p))
p++;
/* line is empty? */
@@ -131,7 +131,7 @@
/* find end of field */
s = p;
- while (*s && !isspace (*s))
+ while (*s && !isspace ((unsigned char)*s))
s++;
if (*s)
*s++ = '\0';
@@ -143,7 +143,7 @@
p = s;
/* skip whitespace */
- while (*p && isspace (*p))
+ while (*p && isspace ((unsigned char)*p))
p++;
/* line is empty? */
--- urjtag/src/bsdl/vhdl_flex.l.orig 2011-11-20 13:10:13.000000000 +0100
+++ urjtag/src/bsdl/vhdl_flex.l 2011-11-20 13:10:47.000000000 +0100
@@ -503,8 +503,8 @@
s = filename;
while (*s)
{
- if (islower (*s))
- *s = toupper (*s);
+ if (islower ((unsigned char)*s))
+ *s = toupper ((unsigned char)*s);
s++;
}
--- urjtag/src/svf/svf_flex.l.orig 2011-11-20 13:00:03.000000000 +0100
+++ urjtag/src/svf/svf_flex.l 2011-11-20 13:00:14.000000000 +0100
@@ -350,7 +350,7 @@
for (dst = src; *src; src++)
{
- if (isxdigit (*src))
+ if (isxdigit ((unsigned char)*src))
*dst++ = *src;
}
*dst = '\0';
--- urjtag/src/global/parse.c.orig 2011-11-20 12:58:25.000000000 +0100
+++ urjtag/src/global/parse.c 2011-11-20 12:58:42.000000000 +0100
@@ -77,7 +77,7 @@
while (1)
{
/* eat up leading spaces */
- while (isspace (*c))
+ while (isspace ((unsigned char)*c))
c++;
/* if the command ends here (either by NUL or comment) */
@@ -85,7 +85,7 @@
break;
/* copy the meat (non-space, non-NUL), consider escape and quotes */
- while ((!isspace (*c)
+ while ((!isspace ((unsigned char)*c)
|| escape
|| quote_single
|| quote_double) && *c != '\0')
--- urjtag/src/cmd/cmd_cmd.c.orig 2011-11-20 12:57:15.000000000 +0100
+++ urjtag/src/cmd/cmd_cmd.c 2011-11-20 12:57:44.000000000 +0100
@@ -173,7 +173,7 @@
size_t token_point = 0;
/* Skip all leading whitespace first to make 2nd loop easier */
- while (isspace (*cs))
+ while (isspace ((unsigned char)*cs))
++cs;
while (*cs)
@@ -183,10 +183,10 @@
++cs;
- if (isspace (*cs))
+ if (isspace ((unsigned char)*cs))
{
++token_point;
- while (isspace (*cs))
+ while (isspace ((unsigned char)*cs))
++cs;
}
}
------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure
contains a definitive record of customers, application performance,
security threats, fraudulent activity, and more. Splunk takes this
data and makes sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-novd2d
_______________________________________________
UrJTAG-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/urjtag-development