Mike Frysinger wrote:

> see how this gpio_core.h works for you.  add netbsd-specific logic
> inside of gpio_core.c, and then build your parallel port driver on top
> of the api exposed in gpio_core.h.  afaict, the api in that header
> should be more than enough to do everything you need ...

Unfortunately not. There is no method to define the GPIO device to be opened
(e.g. "/dev/gpio0"). It has to be opened once, before accessing any pin.

This would also be needed as an additional parameter when using the gpio
cable. Under NetBSD/OpenBSD each device has its own set of GPIO pins, and
you don't know if it will be /dev/gpio0 or /dev/gpio1 or whatever.

So I added gpio_open() and gpio_close() functions to the gpio_core. And most
gpio_xxx() functions receive a handle, which is returned by gpio_open(), as
an additional argument.

As a result of this modification I also had to adapt the gpio.c cable
driver. Currently it will call gpio_open() with a NULL argument, which will
still work under Linux, but it should be extended for other operating
systems.

The ppbusgpio.c driver was rewritten to use gpio_core. But I'm not really
happy with it. The overhead is even bigger than before. And the last time I
wrote a 100k U-Boot to flash with it took me nearly 5 hours... ;)

It would probably be better to abondon the ppbusgpio.c driver and wait for
ppi support in NetBSD. Using the gpio cable driver with Byteblaster
hardware could be a faster alternative (once the gpio-device argument had
been implemented).


Here is the diff, based on your last diff. But probably my mail client will
corrupt it.
You also find it here: http://sun.hasenbraten.de/~frank/NetBSD/urjtag.diff

--- src/tap/gpio_core.h.orig    2011-12-03 14:37:13.000000000 +0100
+++ src/tap/gpio_core.h 2011-12-03 14:41:15.000000000 +0100
@@ -27,14 +27,18 @@
 #define URJ_GPIO_CORE_H
 
 typedef struct gpio urj_gpio_t;
+typedef struct gpio_pin urj_gpio_pin_t;
 
-extern urj_gpio_t *gpio_request (unsigned gpio);
-extern void gpio_free (urj_gpio_t *gpio);
+extern urj_gpio_t *gpio_open(const char *path);
+extern int gpio_close(urj_gpio_t *handle);
 
-extern int gpio_direction_input (urj_gpio_t *gpio);
-extern int gpio_direction_output (urj_gpio_t *gpio);
+extern urj_gpio_pin_t *gpio_request (urj_gpio_t *handle, unsigned gpio);
+extern void gpio_free (urj_gpio_t *handle, urj_gpio_pin_t *gpio);
 
-extern int gpio_get_value (urj_gpio_t *gpio);
-extern int gpio_set_value (urj_gpio_t *gpio, int value);
+extern int gpio_direction_input (urj_gpio_t *handle, urj_gpio_pin_t *gpio);
+extern int gpio_direction_output (urj_gpio_t *handle, urj_gpio_pin_t
*gpio);
+
+extern int gpio_get_value (urj_gpio_t *handle, urj_gpio_pin_t *gpio);
+extern int gpio_set_value (urj_gpio_t *handle, urj_gpio_pin_t *gpio, int
value);
 
 #endif
--- src/tap/gpio_core.c.orig    2011-12-03 14:37:09.000000000 +0100
+++ src/tap/gpio_core.c 2011-12-03 17:29:57.000000000 +0100
@@ -33,6 +33,24 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/gpio.h>
+#include <sys/ioctl.h>
+#ifdef GPIOPINREAD /* old GPIO API */
+#define gpiorw gpio_pin_op
+#define gpioctl gpio_pin_ctl
+#define GPIO_READ GPIOPINREAD
+#define GPIO_WRITE GPIOPINWRITE
+#define GPIO_CTL GPIOPINCTL
+#else
+#define gpiorw gpio_req
+#define gpioctl gpio_set
+#define GPIO_READ GPIOREAD
+#define GPIO_WRITE GPIOWRITE
+#define GPIO_CTL GPIOSET
+#endif
+#endif
+
 #include <urjtag/log.h>
 
 #include "gpio_core.h"
@@ -44,10 +62,32 @@
 #define GPIO_UNEXPORT_PATH GPIO_PATH "unexport"
 
 struct gpio {
+    const char *path;
+};
+
+struct gpio_pin {
     unsigned gpio;
     int fd_val, fd_dir;
 };
 
+urj_gpio_t *gpio_open(const char *path)
+{
+    urj_gpio_t *handle;
+
+    handle = malloc (sizeof (*handle));
+    if (handle)
+        handle->path = GPIO_PATH;
+    return handle;
+}
+
+int gpio_close(urj_gpio_t *handle)
+{
+    if (handle == NULL)
+        return URJ_STATUS_FAIL;
+    free (handle);
+    return URJ_STATUS_OK;
+}
+
 static int gpio_export (unsigned gpio, int export)
 {
     char *fname;
@@ -71,9 +111,9 @@
     return URJ_STATUS_OK;
 }
 
-urj_gpio_t *gpio_request (unsigned gpio_num)
+urj_gpio_pin_t *gpio_request (urj_gpio_t *handle, unsigned gpio_num)
 {
-    urj_gpio_t *gpio;
+    urj_gpio_pin_t *gpio;
     char fname[50];
     int ret;
 
@@ -88,14 +128,14 @@
     gpio->gpio = gpio_num;
 
     snprintf (fname, sizeof (fname) - 1,
-        "%sgpio%u/direction", GPIO_PATH, gpio_num);
+        "%sgpio%u/direction", handle->path, gpio_num);
     fname[sizeof (fname) - 1] = '\0';
     gpio->fd_dir = open (fname, O_RDWR);
     if (gpio->fd_dir < 0)
         goto err;
 
     snprintf (fname, sizeof (fname) - 1,
-        "%sgpio%u/value", GPIO_PATH, gpio_num);
+        "%sgpio%u/value", handle->path, gpio_num);
     fname[sizeof (fname) - 1] = '\0';
     gpio->fd_val = open (fname, O_RDWR);
     if (gpio->fd_val < 0)
@@ -110,7 +150,7 @@
     return NULL;
 }
 
-void gpio_free (urj_gpio_t *gpio)
+void gpio_free (urj_gpio_t *handle, urj_gpio_pin_t *gpio)
 {
     gpio_export (gpio->gpio, 0);
     close (gpio->fd_dir);
@@ -123,17 +163,17 @@
     return pwrite (fd, string, len, 0) == len ? URJ_STATUS_OK :
URJ_STATUS_FAIL;
 }
 
-int gpio_direction_output (urj_gpio_t *gpio)
+int gpio_direction_output (urj_gpio_t *handle, urj_gpio_pin_t *gpio)
 {
     return gpio_write_string (gpio->fd_dir, "out", 3);
 }
 
-int gpio_direction_input (urj_gpio_t *gpio)
+int gpio_direction_input (urj_gpio_t *handle, urj_gpio_pin_t *gpio)
 {
     return gpio_write_string (gpio->fd_dir, "in", 2);
 }
 
-int gpio_get_value (urj_gpio_t *gpio)
+int gpio_get_value (urj_gpio_t *handle, urj_gpio_pin_t *gpio)
 {
     ssize_t ret;
     char value;
@@ -143,16 +183,134 @@
     if (ret != 1)
     {
         urj_warning (_("Error getting value of gpio %u\n"), gpio->gpio);
-        return URJ_STATUS_FAIL;
+        return -1;
     }
 
     return value == '1';
 }
 
-int gpio_set_value (urj_gpio_t *gpio, int value)
+int gpio_set_value (urj_gpio_t *handle, urj_gpio_pin_t *gpio, int value)
 {
     char gpio_value = value + '0';
     return gpio_write_string (gpio->fd_val, &gpio_value, 1);
 }
 
-#endif
+#endif /* __linux__ */
+
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+
+struct gpio {
+    int fd;
+};
+
+struct gpio_pin {
+    int pin;
+    int value;
+};
+
+urj_gpio_t *gpio_open(const char *path)
+{
+    urj_gpio_t *handle;
+
+    handle = malloc (sizeof (*handle));
+    if (handle == NULL)
+        return NULL;
+
+    handle->fd = open (path, O_RDWR);
+    if (handle->fd < 0)
+    {
+        free (handle);
+        return NULL;
+    }
+
+    return handle;
+}
+
+int gpio_close(urj_gpio_t *handle)
+{
+    if (close (handle->fd) != 0)
+         return URJ_STATUS_FAIL;
+
+    free (handle);
+    return URJ_STATUS_OK;
+}
+
+urj_gpio_pin_t *gpio_request (urj_gpio_t *handle, unsigned pin)
+{
+    urj_gpio_pin_t *gpio;
+    struct gpiorw req;
+
+    memset (&req, 0, sizeof(req));
+    req.gp_pin = pin;
+    if (ioctl (handle->fd, GPIO_READ, &req) == -1)
+        return NULL;
+
+    gpio = malloc (sizeof (*gpio));
+    if (!gpio)
+        return NULL;
+
+    gpio->pin = pin;
+    gpio->value = req.gp_value;
+    return gpio;
+}
+
+void gpio_free (urj_gpio_t *handle, urj_gpio_pin_t *gpio)
+{
+    free (gpio);
+}
+
+static int gpio_direction (urj_gpio_t *handle, urj_gpio_pin_t *gpio, int
dir)
+{
+    struct gpioctl ctl;
+
+    memset (&ctl, 0, sizeof(ctl));
+    ctl.gp_pin = gpio->pin;
+    ctl.gp_flags = dir;
+    ioctl (handle->fd, GPIO_CTL, &ctl); /* XXX ignore result */
+    return URJ_STATUS_OK;
+}
+
+int gpio_direction_output (urj_gpio_t *handle, urj_gpio_pin_t *gpio)
+{
+    return gpio_direction(handle, gpio, GPIO_PIN_OUTPUT);
+}
+
+int gpio_direction_input (urj_gpio_t *handle, urj_gpio_pin_t *gpio)
+{
+    return gpio_direction(handle, gpio, GPIO_PIN_INPUT);
+}
+
+int gpio_get_value (urj_gpio_t *handle, urj_gpio_pin_t *gpio)
+{
+    struct gpiorw req;
+
+    memset (&req, 0, sizeof(req));
+    req.gp_pin = gpio->pin;
+    if (ioctl (handle->fd, GPIO_READ, &req) == -1)
+    {
+        urj_warning (_("Error getting value of gpio %d\n"), gpio->pin);
+        return -1;
+    }
+    gpio->value = req.gp_value;
+    return gpio->value == GPIO_PIN_HIGH;
+}
+
+int gpio_set_value (urj_gpio_t *handle, urj_gpio_pin_t *gpio, int value)
+{
+    struct gpiorw req;
+
+    value = value == GPIO_PIN_HIGH;
+    if (gpio->value != value)
+    {
+        memset (&req, 0, sizeof(req));
+        req.gp_pin = gpio->pin;
+        req.gp_value = value;
+        if (ioctl (handle->fd, GPIO_WRITE, &req) == -1)
+            return URJ_STATUS_FAIL;
+        gpio->value = value;
+    }
+    return URJ_STATUS_OK;
+}
+
+#endif /* __NetBSD__ || __OpenBSD__ */
--- src/tap/cable/gpio.c.orig   2011-12-03 15:13:37.000000000 +0100
+++ src/tap/cable/gpio.c    2011-12-03 15:35:13.000000000 +0100
@@ -51,52 +51,60 @@
 };
 
 typedef struct {
-    urj_gpio_t *gpios[4];
-    unsigned    jtag_gpios[4];
-    int         signals;
-    uint32_t    lastout;
+    urj_gpio_t      *gpioh;
+    urj_gpio_pin_t  *gpios[4];
+    unsigned        jtag_gpios[4];
+    int             signals;
+    uint32_t        lastout;
 } gpio_params_t;
 
 static int
-gpio_open (urj_cable_t *cable)
+gpio_cable_open (urj_cable_t *cable)
 {
     gpio_params_t *p = cable->params;
     int i;
 
+    p->gpioh = gpio_open(NULL);  /* XXX FIXME! */
+    if (p->gpioh == NULL)
+        return URJ_STATUS_FAIL;
+
     /* Export all gpios */
     for (i = 0; i < GPIO_REQUIRED; i++)
     {
         unsigned gpio = p->jtag_gpios[i];
 
-        p->gpios[i] = gpio_request (gpio);
+        p->gpios[i] = gpio_request (p->gpioh, gpio);
         if (!p->gpios[i])
         {
             urj_warning (_("gpio[%d] %u cannot be exported\n"), i, gpio);
             return URJ_STATUS_FAIL;
         }
         if (i == GPIO_TDO)
-            gpio_direction_input (p->gpios[i]);
+            gpio_direction_input (p->gpioh, p->gpios[i]);
         else
-            gpio_direction_output (p->gpios[i]);
+            gpio_direction_output (p->gpioh, p->gpios[i]);
    }
 
     return URJ_STATUS_OK;
 }
 
 static int
-gpio_close (urj_cable_t *cable)
+gpio_cable_close (urj_cable_t *cable)
 {
     gpio_params_t *p = cable->params;
     int i;
 
+    if (p->gpioh == NULL)
+        return URJ_STATUS_FAIL;
+
     for (i = 0; i < GPIO_REQUIRED; i++)
-        gpio_free (p->gpios[i]);
+        gpio_free (p->gpioh, p->gpios[i]);
 
     return URJ_STATUS_OK;
 }
 
 static void
-gpio_help (urj_log_level_t ll, const char *cablename)
+gpio_cable_help (urj_log_level_t ll, const char *cablename)
 {
     urj_log (ll,
         _("Usage: cable %s tdi=<gpio_tdi> tdo=<gpio_tdo> "
@@ -105,7 +113,7 @@
 }
 
 static int
-gpio_connect (urj_cable_t *cable, const urj_param_t *params[])
+gpio_cable_connect (urj_cable_t *cable, const urj_param_t *params[])
 {
     gpio_params_t *cable_params;
     int i;
@@ -159,7 +167,7 @@
         if (cable_params->jtag_gpios[i] == GPIO_REQUIRED)
         {
             urj_error_set (URJ_ERROR_SYNTAX, _("missing required
gpios\n"));
-            gpio_help (URJ_ERROR_SYNTAX, "gpio");
+            gpio_cable_help (URJ_ERROR_SYNTAX, "gpio");
             return URJ_STATUS_FAIL;
         }
 
@@ -171,10 +179,10 @@
 }
 
 static void
-gpio_disconnect (urj_cable_t *cable)
+gpio_cable_disconnect (urj_cable_t *cable)
 {
     urj_tap_chain_disconnect (cable->chain);
-    gpio_close (cable);
+    gpio_cable_close (cable);
 }
 
 static void
@@ -185,11 +193,11 @@
 }
 
 static int
-gpio_init (urj_cable_t *cable)
+gpio_cable_init (urj_cable_t *cable)
 {
     gpio_params_t *p = cable->params;
 
-    if (gpio_open (cable) != URJ_STATUS_OK)
+    if (gpio_cable_open (cable) != URJ_STATUS_OK)
         return URJ_STATUS_FAIL;
 
     p->signals = URJ_POD_CS_TRST;
@@ -198,13 +206,13 @@
 }
 
 static void
-gpio_done (urj_cable_t *cable)
+gpio_cable_done (urj_cable_t *cable)
 {
-    gpio_close (cable);
+    gpio_cable_close (cable);
 }
 
 static void
-gpio_clock (urj_cable_t *cable, int tms, int tdi, int n)
+gpio_cable_clock (urj_cable_t *cable, int tms, int tdi, int n)
 {
     gpio_params_t *p = cable->params;
     int i;
@@ -212,34 +220,34 @@
     tms = tms ? 1 : 0;
     tdi = tdi ? 1 : 0;
 
-    gpio_set_value (p->gpios[GPIO_TMS], tms);
-    gpio_set_value (p->gpios[GPIO_TDI], tdi);
+    gpio_set_value (p->gpioh, p->gpios[GPIO_TMS], tms);
+    gpio_set_value (p->gpioh, p->gpios[GPIO_TDI], tdi);
 
     for (i = 0; i < n; i++)
     {
-        gpio_set_value (p->gpios[GPIO_TCK], 0);
-        gpio_set_value (p->gpios[GPIO_TCK], 1);
-        gpio_set_value (p->gpios[GPIO_TCK], 0);
+        gpio_set_value (p->gpioh, p->gpios[GPIO_TCK], 0);
+        gpio_set_value (p->gpioh, p->gpios[GPIO_TCK], 1);
+        gpio_set_value (p->gpioh, p->gpios[GPIO_TCK], 0);
     }
 }
 
 static int
-gpio_get_tdo ( urj_cable_t *cable )
+gpio_cable_get_tdo ( urj_cable_t *cable )
 {
     gpio_params_t *p = cable->params;
 
-    gpio_set_value(p->gpios[GPIO_TCK], 0);
-    gpio_set_value(p->gpios[GPIO_TDI], 0);
-    gpio_set_value(p->gpios[GPIO_TMS], 0);
+    gpio_set_value(p->gpioh, p->gpios[GPIO_TCK], 0);
+    gpio_set_value(p->gpioh, p->gpios[GPIO_TDI], 0);
+    gpio_set_value(p->gpioh, p->gpios[GPIO_TMS], 0);
     p->lastout &= ~(URJ_POD_CS_TMS | URJ_POD_CS_TDI | URJ_POD_CS_TCK);
 
     urj_tap_cable_wait (cable);
 
-    return gpio_get_value (p->gpios[GPIO_TDO]);
+    return gpio_get_value (p->gpioh, p->gpios[GPIO_TDO]);
 }
 
 static int
-gpio_current_signals (urj_cable_t *cable)
+gpio_cable_current_signals (urj_cable_t *cable)
 {
     gpio_params_t *p = cable->params;
 
@@ -253,9 +261,9 @@
 }
 
 static int
-gpio_set_signal (urj_cable_t *cable, int mask, int val)
+gpio_cable_set_signal (urj_cable_t *cable, int mask, int val)
 {
-    int prev_sigs = gpio_current_signals (cable);
+    int prev_sigs = gpio_cable_current_signals (cable);
     gpio_params_t *p = cable->params;
 
     mask &= (URJ_POD_CS_TDI | URJ_POD_CS_TCK | URJ_POD_CS_TMS); // only
these can be modified
@@ -263,11 +271,11 @@
     if (mask != 0)
     {
         if (mask & URJ_POD_CS_TMS)
-            gpio_set_value (p->gpios[GPIO_TMS], val & URJ_POD_CS_TMS);
+            gpio_set_value (p->gpioh, p->gpios[GPIO_TMS], val &
URJ_POD_CS_TMS);
         if (mask & URJ_POD_CS_TDI)
-            gpio_set_value (p->gpios[GPIO_TDI], val & URJ_POD_CS_TDI);
+            gpio_set_value (p->gpioh, p->gpios[GPIO_TDI], val &
URJ_POD_CS_TDI);
         if (mask & URJ_POD_CS_TCK)
-            gpio_set_value (p->gpios[GPIO_TCK], val & URJ_POD_CS_TCK);
+            gpio_set_value (p->gpioh, p->gpios[GPIO_TCK], val &
URJ_POD_CS_TCK);
     }
 
     p->lastout = val & mask;
@@ -276,26 +284,26 @@
 }
 
 static int
-gpio_get_signal (urj_cable_t *cable, urj_pod_sigsel_t sig)
+gpio_cable_get_signal (urj_cable_t *cable, urj_pod_sigsel_t sig)
 {
-    return (gpio_current_signals (cable) & sig) ? 1 : 0;
+    return (gpio_cable_current_signals (cable) & sig) ? 1 : 0;
 }
 
 const urj_cable_driver_t urj_tap_cable_gpio_driver = {
     "gpio",
     N_("GPIO JTAG Chain"),
     URJ_CABLE_DEVICE_OTHER,
-    { .other = gpio_connect, },
-    gpio_disconnect,
+    { .other = gpio_cable_connect, },
+    gpio_cable_disconnect,
     gpio_cable_free,
-    gpio_init,
-    gpio_done,
+    gpio_cable_init,
+    gpio_cable_done,
     urj_tap_cable_generic_set_frequency,
-    gpio_clock,
-    gpio_get_tdo,
+    gpio_cable_clock,
+    gpio_cable_get_tdo,
     urj_tap_cable_generic_transfer,
-    gpio_set_signal,
-    gpio_get_signal,
+    gpio_cable_set_signal,
+    gpio_cable_get_signal,
     urj_tap_cable_generic_flush_one_by_one,
-    gpio_help
+    gpio_cable_help
 };
--- /dev/null   2011-12-03 17:54:43.000000000 +0100
+++ src/tap/parport/ppbusgpio.c 2011-12-03 17:36:53.000000000 +0100
@@ -0,0 +1,267 @@
+/*
+ * $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 <stdlib.h>
+#include <string.h>
+
+#include <urjtag/error.h>
+#include <urjtag/log.h>
+#include <urjtag/parport.h>
+#include <urjtag/cable.h>
+
+#include "../parport.h"
+#include "gpio_core.h"
+
+static port_node_t *ports = NULL;       /* gpio parallel ports */
+
+typedef struct {
+   char *portname;
+   urj_gpio_t *handle;
+   urj_gpio_pin_t *gpio[17];
+   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;
+    }
+
+    memset (params, 0, sizeof(*params));
+    params->portname = portname;
+
+    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_parport_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_parport_open (urj_parport_t *parport)
+{
+    gpio_params_t *p = parport->params;
+    unsigned pin;
+
+    p->handle = gpio_open (p->portname);
+    if (p->handle == NULL) {
+        urj_error_IO_set ("Cannot open(%s)", p->portname);
+        return URJ_STATUS_FAIL;
+    }
+
+    /* Initialize all GPIO pins with 0 */
+    for (pin = 0; pin < 17; pin++) {
+        p->gpio[pin] = gpio_request (p->handle, pin);
+        if (p->gpio[pin] == NULL) {
+            gpio_close(p->handle);
+            p->handle = NULL;
+            return URJ_STATUS_FAIL;
+        }
+        (void)gpio_set_value (p->handle, p->gpio[pin], 0);
+    }
+    p->data = p->stat = p->ctrl = 0;
+
+    return URJ_STATUS_OK;
+}
+
+static int
+gpio_parport_close (urj_parport_t *parport)
+{
+    int r = URJ_STATUS_OK;
+    unsigned pin;
+    gpio_params_t *p = parport->params;
+
+    for (pin = 0; pin < 17; pin++)
+        if (p->gpio[pin])
+            gpio_free (p->handle, p->gpio[pin]);
+
+    if (gpio_close (p->handle) != URJ_STATUS_OK) {
+        urj_error_IO_set ("Cannot close(%p)", p->handle);
+        return URJ_STATUS_FAIL;
+    }
+
+    p->handle = NULL;
+    return r;
+}
+
+static int
+gpio_parport_set_data (urj_parport_t *parport, unsigned char data)
+{
+    gpio_params_t *p = parport->params;
+    uint8_t changed, mask;
+    int i;
+
+    if ((changed = data ^ p->data)) {
+        for (mask = 1, i = 1; i <= 8; mask <<= 1, i++) {
+            if ((changed & mask) != 0) {
+                if (gpio_set_value (p->handle, p->gpio[i], (data & mask) !=
0)
+                    != URJ_STATUS_OK)
+                    return URJ_STATUS_FAIL;
+            }
+        }
+        p->data = data;
+    }
+
+    return URJ_STATUS_OK;
+}
+
+static int
+gpio_parport_get_data (urj_parport_t *parport)
+{
+    gpio_params_t *p = parport->params;
+    int d, i, mask, val;
+
+    for (d = 0, mask = 1, i = 1; i <= 8; mask <<= 1, i++) {
+        val = gpio_get_value (p->handle, p->gpio[i]);
+        if (val < 0)
+            return -1;
+        if (val != 0)
+            d |= mask;
+    }
+    p->data = d;
+
+    return d;
+}
+
+static int
+gpio_parport_get_status (urj_parport_t *parport)
+{
+    gpio_params_t *p = parport->params;
+    int d, i, mask, val;
+    int pins[8] = { 0, 0, 0, 14, 12, 11, 9, 10 };
+
+    for (d = 0, mask = (1<<3), i = 3; i < 8; mask <<= 1, i++) {
+        val = gpio_get_value (p->handle, p->gpio[pins[i]]);
+        if (val < 0)
+            return -1;
+        if (val != 0)
+            d |= mask;
+    }
+    p->stat = d;
+
+    return d;
+}
+
+static int
+gpio_parport_set_control (urj_parport_t *parport, unsigned char data)
+{
+    gpio_params_t *p = parport->params;
+    unsigned char changed, mask;
+    int i;
+    int pins[4] = { 0, 13, 15, 16 };
+
+    if ((changed = data ^ p->ctrl)) {
+        for (mask = 1, i = 0; i < 4; mask <<= 1, i++) {
+            if ((changed & mask) != 0) {
+                if (gpio_set_value (p->handle, p->gpio[pins[i]],
+                    (data & mask) != 0) != URJ_STATUS_OK)
+                    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_parport_connect,
+    gpio_parport_free,
+    gpio_parport_open,
+    gpio_parport_close,
+    gpio_parport_set_data,
+    gpio_parport_get_data,
+    gpio_parport_get_status,
+    gpio_parport_set_control
+};


Regards,

-- 
Frank Wille


------------------------------------------------------------------------------
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

Reply via email to