--- 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 #include +#if defined(__NetBSD__) || defined(__OpenBSD__) +#include +#include +#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 #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= 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 , 2011. + * + */ + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#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 +};