# HG changeset patch # User Florian Pose # Date 1255449392 -7200 # Node ID 49430a3fe73df54b5b65b773c91fe69aa002b063 # Parent f16c834600d41264b76f3ccffdefbc1fa548abfc Basic generic Ethernet device module. diff -r f16c834600d4 -r 49430a3fe73d configure.ac --- a/configure.ac Tue Oct 13 16:52:56 2009 +0200 +++ b/configure.ac Tue Oct 13 17:56:32 2009 +0200 @@ -102,6 +102,29 @@ AC_MSG_RESULT([$LINUX_SOURCE_DIR (Kernel $LINUX_KERNEL_RELEASE)]) #------------------------------------------------------------------------------ +# Generic Ethernet driver +#------------------------------------------------------------------------------ + +AC_ARG_ENABLE([generic], + AS_HELP_STRING([--enable-generic], + [Enable generic Ethernet driver]), + [ + case "${enableval}" in + yes) enablegeneric=1 + ;; + no) enablegeneric=0 + ;; + *) AC_MSG_ERROR([Invalid value for --enable-generic]) + ;; + esac + ], + [enablegeneric=0] +) + +AM_CONDITIONAL(ENABLE_GENERIC, test "x$enablegeneric" = "x1") +AC_SUBST(ENABLE_GENERIC,[$enablegeneric]) + +#------------------------------------------------------------------------------ # 8139too driver #------------------------------------------------------------------------------ diff -r f16c834600d4 -r 49430a3fe73d devices/Kbuild.in --- a/devices/Kbuild.in Tue Oct 13 16:52:56 2009 +0200 +++ b/devices/Kbuild.in Tue Oct 13 17:56:32 2009 +0200 @@ -37,6 +37,13 @@ hg id -i $(src)/.. 2>/dev/null || echo "unknown"; \ fi) +ifeq (@ENABLE_GENERIC@,1) + EC_GENERIC_OBJ := generic.o + obj-m += ec_generic.o + ec_generic-objs := $(EC_GENERIC_OBJ) + CFLAGS_$(EC_GENERIC_OBJ) = -DREV=$(REV) +endif + ifeq (@ENABLE_8139TOO@,1) EC_8139TOO_OBJ := 8139too-@KERNEL_8139TOO@-ethercat.o obj-m += ec_8139too.o diff -r f16c834600d4 -r 49430a3fe73d devices/Makefile.am --- a/devices/Makefile.am Tue Oct 13 16:52:56 2009 +0200 +++ b/devices/Makefile.am Tue Oct 13 17:56:32 2009 +0200 @@ -68,6 +68,7 @@ e100-2.6.29-ethercat.c \ e100-2.6.29-orig.c \ ecdev.h \ + generic.c \ r8169-2.6.24-ethercat.c \ r8169-2.6.24-orig.c \ r8169-2.6.28-ethercat.c \ @@ -86,6 +87,9 @@ modules_install: mkdir -p $(DESTDIR)$(LINUX_MOD_PATH) +if ENABLE_GENERIC + cp $(srcdir)/ec_generic.ko $(DESTDIR)$(LINUX_MOD_PATH) +endif if ENABLE_8139TOO cp $(srcdir)/ec_8139too.ko $(DESTDIR)$(LINUX_MOD_PATH) endif diff -r f16c834600d4 -r 49430a3fe73d devices/generic.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/devices/generic.c Tue Oct 13 17:56:32 2009 +0200 @@ -0,0 +1,342 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * The IgH EtherCAT Master 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 the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + *****************************************************************************/ + +/** \file + * EtherCAT generic Ethernet device module. + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include /* ARPHRD_ETHER */ +#include + +#include "../globals.h" +#include "ecdev.h" + +#define PFX "ec_generic: " + +/*****************************************************************************/ + +int __init ec_gen_init_module(void); +void __exit ec_gen_cleanup_module(void); + +/*****************************************************************************/ + +/** \cond */ + +MODULE_AUTHOR("Florian Pose "); +MODULE_DESCRIPTION("EtherCAT master generic Ethernet device module"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(EC_MASTER_VERSION); + +/** \endcond */ + +struct list_head generic_devices; + +typedef struct { + struct list_head list; + struct net_device *netdev; +#if 0 + struct net_device *real_netdev; +#endif + ec_device_t *ecdev; +} ec_gen_device_t; + +int ec_gen_device_open(ec_gen_device_t *); +int ec_gen_device_stop(ec_gen_device_t *); +int ec_gen_device_start_xmit(ec_gen_device_t *, struct sk_buff *); + +/*****************************************************************************/ + +static int ec_gen_netdev_open(struct net_device *dev) +{ + ec_gen_device_t *gendev = *((ec_gen_device_t **) netdev_priv(dev)); + return ec_gen_device_open(gendev); +} + +/*****************************************************************************/ + +static int ec_gen_netdev_stop(struct net_device *dev) +{ + ec_gen_device_t *gendev = *((ec_gen_device_t **) netdev_priv(dev)); + return ec_gen_device_stop(gendev); +} + +/*****************************************************************************/ + +static int ec_gen_netdev_start_xmit( + struct sk_buff *skb, + struct net_device *dev + ) +{ + ec_gen_device_t *gendev = *((ec_gen_device_t **) netdev_priv(dev)); + return ec_gen_device_start_xmit(gendev, skb); +} + +/*****************************************************************************/ + +void ec_gen_poll(struct net_device *dev) +{ +} + +/*****************************************************************************/ + +static const struct net_device_ops ec_gen_netdev_ops = { + .ndo_open = ec_gen_netdev_open, + .ndo_stop = ec_gen_netdev_stop, + .ndo_start_xmit = ec_gen_netdev_start_xmit, +}; + +/*****************************************************************************/ + +/** Init generic device. + */ +int ec_gen_device_init( + ec_gen_device_t *dev, + struct net_device *real_netdev + ) +{ + ec_gen_device_t **priv; + char null = 0x00; + + dev->ecdev = NULL; +#if 0 + dev->real_netdev = real_netdev; +#endif + + dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null, ether_setup); + if (!dev->netdev) { + return -ENOMEM; + } + memcpy(dev->netdev->dev_addr, real_netdev->dev_addr, ETH_ALEN); + dev->netdev->netdev_ops = &ec_gen_netdev_ops; + priv = netdev_priv(dev->netdev); + *priv = dev; + + return 0; +} + +/*****************************************************************************/ + +/** Clear generic device. + */ +void ec_gen_device_clear( + ec_gen_device_t *dev + ) +{ + if (dev->ecdev) { + ecdev_close(dev->ecdev); + ecdev_withdraw(dev->ecdev); + } + free_netdev(dev->netdev); +} + +/*****************************************************************************/ + +/** Offer generic device to master. + */ +int ec_gen_device_offer( + ec_gen_device_t *dev + ) +{ + int ret = 0; + + dev->ecdev = ecdev_offer(dev->netdev, ec_gen_poll, THIS_MODULE); + if (dev->ecdev) { + if (ecdev_open(dev->ecdev)) { + ecdev_withdraw(dev->ecdev); + dev->ecdev = NULL; + } else { + ret = 1; + } + } + + return ret; +} + +/*****************************************************************************/ + +/** Open the device. + */ +int ec_gen_device_open( + ec_gen_device_t *dev + ) +{ + int ret = 0; + +#if 0 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) + ret = dev->real_netdev->netdev_ops->ndo_open(dev->real_netdev); +#else + ret = dev->real_netdev->open(dev->real_netdev); +#endif +#endif + + return ret; +} + +/*****************************************************************************/ + +/** Stop the device. + */ +int ec_gen_device_stop( + ec_gen_device_t *dev + ) +{ + int ret = 0; + +#if 0 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) + ret = dev->real_netdev->netdev_ops->ndo_stop(dev->real_netdev); +#else + ret = dev->real_netdev->stop(dev->real_netdev); +#endif +#endif + + return ret; +} + +/*****************************************************************************/ + +int ec_gen_device_start_xmit( + ec_gen_device_t *dev, + struct sk_buff *skb + ) +{ + return 0; +} + +/*****************************************************************************/ + +/** Offer device. + */ +int offer_device( + struct net_device *netdev + ) +{ + ec_gen_device_t *gendev; + int ret = 0; + + gendev = kmalloc(sizeof(ec_gen_device_t), GFP_KERNEL); + if (!gendev) { + return -ENOMEM; + } + + ret = ec_gen_device_init(gendev, netdev); + if (ret) { + kfree(gendev); + return ret; + } + + if (ec_gen_device_offer(gendev)) { + list_add_tail(&gendev->list, &generic_devices); + } else { + ec_gen_device_clear(gendev); + kfree(gendev); + } + + return ret; +} + +/*****************************************************************************/ + +/** Clear devices. + */ +void clear_devices(void) +{ + ec_gen_device_t *gendev, *next; + + list_for_each_entry_safe(gendev, next, &generic_devices, list) { + list_del(&gendev->list); + ec_gen_device_clear(gendev); + kfree(gendev); + } +} + +/*****************************************************************************/ + +/** Module initialization. + * + * Initializes \a master_count masters. + * \return 0 on success, else < 0 + */ +int __init ec_gen_init_module(void) +{ + int ret = 0; + struct net_device *netdev; + + printk(KERN_INFO PFX "EtherCAT master generic Ethernet device module %s\n", + EC_MASTER_VERSION); + + INIT_LIST_HEAD(&generic_devices); + + read_lock(&dev_base_lock); + for_each_netdev(&init_net, netdev) { + if (netdev->type != ARPHRD_ETHER) + continue; + ret = offer_device(netdev); + if (ret) { + read_unlock(&dev_base_lock); + goto out_err; + } + } + read_unlock(&dev_base_lock); + return ret; + +out_err: + clear_devices(); + return ret; +} + +/*****************************************************************************/ + +/** Module cleanup. + * + * Clears all master instances. + */ +void __exit ec_gen_cleanup_module(void) +{ + clear_devices(); + printk(KERN_INFO PFX "Unloading.\n"); +} + +/*****************************************************************************/ + +/** \cond */ + +module_init(ec_gen_init_module); +module_exit(ec_gen_cleanup_module); + +/** \endcond */ + +/*****************************************************************************/