diff --git a/jtag/ChangeLog b/jtag/ChangeLog index 5048d214..8c3a60d7 100644 --- a/jtag/ChangeLog +++ b/jtag/ChangeLog @@ -1,5 +1,9 @@ 2007-12-15 Kolja Waschk + * configure.ac, tap/parport/parport.c, tap/parport/ppi.c, + tap/parport/direct.c: Adapted openwince patch by Daniel + O'Connor, [1235990] Add support for FreeBSD's ppi interface + (closes our copy of that tracker item, 1829585) * src/cmd/cable.c, include/cable.h, src/tap/cable/*.c: Add help function to every cable; temporarily allow old syntax for cable command when used for parallel port cables diff --git a/jtag/configure.ac b/jtag/configure.ac index 1b249e2c..0395efa3 100644 --- a/jtag/configure.ac +++ b/jtag/configure.ac @@ -171,6 +171,7 @@ AC_CHECK_FUNCS(swprintf) AC_CHECK_FUNC(clock_gettime, [], [ AC_CHECK_LIB(rt, clock_gettime) ]) AC_CHECK_HEADERS(linux/ppdev.h) +AC_CHECK_HEADERS(dev/ppbus/ppi.h) VL_LIB_READLINE diff --git a/jtag/src/tap/Makefile.am b/jtag/src/tap/Makefile.am index 0d3282e5..27a93139 100644 --- a/jtag/src/tap/Makefile.am +++ b/jtag/src/tap/Makefile.am @@ -33,6 +33,7 @@ libtap_a_SOURCES = \ parport.c \ parport/direct.c \ parport/ppdev.c \ + parport/ppi.c \ cable.c \ cable/generic.h \ cable/generic.c \ diff --git a/jtag/src/tap/parport.c b/jtag/src/tap/parport.c index 869c2d7c..bcd74401 100644 --- a/jtag/src/tap/parport.c +++ b/jtag/src/tap/parport.c @@ -43,6 +43,9 @@ extern parport_driver_t ftdi_mpsse_parport_driver; #ifdef HAVE_LIBUSB extern parport_driver_t xpcu_pp_driver; #endif /* HAVE_LIBUSB */ +#ifdef HAVE_DEV_PPBUS_PPI_H +extern parport_driver_t ppi_parport_driver; +#endif /* HAVE_DEV_PPBUS_PPI_H */ parport_driver_t *parport_drivers[] = { #if defined(HAVE_IOPERM) || defined(HAVE_I386_SET_IOPERM) @@ -62,9 +65,13 @@ parport_driver_t *parport_drivers[] = { #ifdef HAVE_LIBUSB &xpcu_pp_driver, #endif /* HAVE_LIBUSB */ +#ifdef HAVE_DEV_PPBUS_PPI_H + &ppi_parport_driver, +#endif /* HAVE_DEV_PPBUS_PPI_H */ NULL /* last must be NULL */ }; + int parport_open( parport_t *port ) { diff --git a/jtag/src/tap/parport/direct.c b/jtag/src/tap/parport/direct.c index 15c0deaa..5927d833 100644 --- a/jtag/src/tap/parport/direct.c +++ b/jtag/src/tap/parport/direct.c @@ -46,6 +46,10 @@ static __inline int ioperm( unsigned long from, unsigned long num, int permit ) { +#ifdef __FreeBSD__ + if (i386_set_ioperm( from, num, permit ) == -1) + return -1; +#else u_long ports[32]; u_long i; @@ -60,14 +64,17 @@ ioperm( unsigned long from, unsigned long num, int permit ) if (i386_set_ioperm( ports ) == -1) return -1; - +#endif return 0; } static __inline int iopl( int level ) { +#ifndef __FreeBSD__ return i386_iopl( level ); +#endif + return 0; } static __inline unsigned char diff --git a/jtag/src/tap/parport/ppi.c b/jtag/src/tap/parport/ppi.c new file mode 100644 index 00000000..e92805d0 --- /dev/null +++ b/jtag/src/tap/parport/ppi.c @@ -0,0 +1,222 @@ +/* + * $Id$ + * + * FreeBSD ppi Driver + * Copyright (C) 2005 Daniel O'Connor + * + * 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 Daniel O'Connor July 2005. + * + */ + +#include "sysdep.h" + +#ifdef HAVE_DEV_PPBUS_PPI_H + +#include +#include +#include +#include + +#include +#include + +#include "parport.h" +#include "cable.h" + +parport_driver_t ppi_parport_driver; + +typedef struct port_node_t port_node_t; + +struct port_node_t { + parport_t *port; + port_node_t *next; +}; + +static port_node_t *ports = NULL; /* ppi parallel ports */ + +typedef struct { + char *portname; + int fd; +} ppi_params_t; + +static parport_t * +ppi_parport_alloc( const char *port ) +{ + ppi_params_t *params = malloc( sizeof *params ); + char *portname = strdup( port ); + 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 ); + return NULL; + } + + params->portname = portname; + params->fd = -1; + + parport->params = params; + parport->driver = &ppi_parport_driver; + parport->cable = NULL; + + node->port = parport; + node->next = ports; + + ports = node; + + return parport; +} + +static void +ppi_parport_free( 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( ((ppi_params_t *) port->params)->portname ); + free( port->params ); + free( port ); +} + +static cable_t * +ppi_connect( const char **par, int parnum ) +{ + port_node_t *pn; + parport_t *parport; + + if (parnum != 1) { + printf( _("Syntax error!\n") ); + return NULL; + } + + for (pn = ports; pn; pn = pn->next) + if (strcmp( pn->port->params, par[0] ) == 0) { + printf( _("Disconnecting %s from ppi port %s\n"), _(pn->port->cable->driver->description), par[0] ); + pn->port->cable->driver->disconnect( pn->port->cable ); + break; + } + + printf( _("Initializing on ppi port %s\n"), par[0] ); + + parport = ppi_parport_alloc( par[0] ); + if (!parport) { + printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ ); + return NULL; + } + + return parport; +} + +static int +ppi_open( parport_t *parport ) +{ + ppi_params_t *p = parport->params; + + p->fd = open( p->portname, O_RDWR ); + if (p->fd < 0) + return -1; + + return 0; +} + +static int +ppi_close( parport_t *parport ) +{ + int r = 0; + ppi_params_t *p = parport->params; + + if (close( p->fd ) != 0) + return -1; + + p->fd = -1; + return r; +} + +static int +ppi_set_data( parport_t *parport, uint8_t data ) +{ + ppi_params_t *p = parport->params; + + if (ioctl( p->fd, PPISDATA, &data ) == -1) + return -1; + + return 0; +} + +static int +ppi_get_data( parport_t *parport ) +{ + unsigned char d; + ppi_params_t *p = parport->params; + + if (ioctl( p->fd, PPIGDATA, &d ) == -1) + return -1; + + return d; +} + +static int +ppi_get_status( parport_t *parport ) +{ + unsigned char d; + ppi_params_t *p = parport->params; + + if (ioctl( p->fd, PPIGSTATUS, &d ) == -1) + return -1; + + return d ^ 0x80; /* BUSY is inverted */ +} + +static int +ppi_set_control( parport_t *parport, uint8_t data ) +{ + ppi_params_t *p = parport->params; + + data ^= 0x0B; /* SELECT, AUTOFD, and STROBE are inverted */ + + if (ioctl( p->fd, PPIGCTRL, &data ) == -1) + return -1; + + return 0; +} + +parport_driver_t ppi_parport_driver = { + "ppi", + ppi_connect, + ppi_parport_free, + ppi_open, + ppi_close, + ppi_set_data, + ppi_get_data, + ppi_get_status, + ppi_set_control +}; + +#endif /* HAVE_DEV_PPBUS_PPI_H */