devices/generic.c
changeset 1540 49430a3fe73d
child 1541 26ac1c611100
equal deleted inserted replaced
1539:f16c834600d4 1540:49430a3fe73d
       
     1 /******************************************************************************
       
     2  *
       
     3  *  $Id$
       
     4  *
       
     5  *  Copyright (C) 2006-2008  Florian Pose, Ingenieurgemeinschaft IgH
       
     6  *
       
     7  *  This file is part of the IgH EtherCAT Master.
       
     8  *
       
     9  *  The IgH EtherCAT Master is free software; you can redistribute it and/or
       
    10  *  modify it under the terms of the GNU General Public License version 2, as
       
    11  *  published by the Free Software Foundation.
       
    12  *
       
    13  *  The IgH EtherCAT Master is distributed in the hope that it will be useful,
       
    14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
       
    16  *  Public License for more details.
       
    17  *
       
    18  *  You should have received a copy of the GNU General Public License along
       
    19  *  with the IgH EtherCAT Master; if not, write to the Free Software
       
    20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    21  *
       
    22  *  ---
       
    23  *
       
    24  *  The license mentioned above concerns the source code only. Using the
       
    25  *  EtherCAT technology and brand is only permitted in compliance with the
       
    26  *  industrial property and similar rights of Beckhoff Automation GmbH.
       
    27  *
       
    28  *****************************************************************************/
       
    29 
       
    30 /** \file
       
    31  * EtherCAT generic Ethernet device module.
       
    32  */
       
    33 
       
    34 /*****************************************************************************/
       
    35 
       
    36 #include <linux/module.h>
       
    37 #include <linux/device.h>
       
    38 #include <linux/err.h>
       
    39 #include <linux/version.h>
       
    40 #include <linux/if_arp.h> /* ARPHRD_ETHER */
       
    41 #include <linux/etherdevice.h>
       
    42 
       
    43 #include "../globals.h"
       
    44 #include "ecdev.h"
       
    45 
       
    46 #define PFX "ec_generic: "
       
    47 
       
    48 /*****************************************************************************/
       
    49 
       
    50 int __init ec_gen_init_module(void);
       
    51 void __exit ec_gen_cleanup_module(void);
       
    52 
       
    53 /*****************************************************************************/
       
    54 
       
    55 /** \cond */
       
    56 
       
    57 MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
       
    58 MODULE_DESCRIPTION("EtherCAT master generic Ethernet device module");
       
    59 MODULE_LICENSE("GPL");
       
    60 MODULE_VERSION(EC_MASTER_VERSION);
       
    61 
       
    62 /** \endcond */
       
    63 
       
    64 struct list_head generic_devices;
       
    65 
       
    66 typedef struct {
       
    67     struct list_head list;
       
    68     struct net_device *netdev;
       
    69 #if 0
       
    70     struct net_device *real_netdev;
       
    71 #endif
       
    72     ec_device_t *ecdev;
       
    73 } ec_gen_device_t;
       
    74 
       
    75 int ec_gen_device_open(ec_gen_device_t *);
       
    76 int ec_gen_device_stop(ec_gen_device_t *);
       
    77 int ec_gen_device_start_xmit(ec_gen_device_t *, struct sk_buff *);
       
    78 
       
    79 /*****************************************************************************/
       
    80 
       
    81 static int ec_gen_netdev_open(struct net_device *dev)
       
    82 {
       
    83     ec_gen_device_t *gendev = *((ec_gen_device_t **) netdev_priv(dev));
       
    84     return ec_gen_device_open(gendev);
       
    85 }
       
    86 
       
    87 /*****************************************************************************/
       
    88 
       
    89 static int ec_gen_netdev_stop(struct net_device *dev)
       
    90 {
       
    91     ec_gen_device_t *gendev = *((ec_gen_device_t **) netdev_priv(dev));
       
    92     return ec_gen_device_stop(gendev);
       
    93 }
       
    94 
       
    95 /*****************************************************************************/
       
    96 
       
    97 static int ec_gen_netdev_start_xmit(
       
    98         struct sk_buff *skb,
       
    99         struct net_device *dev
       
   100         )
       
   101 {
       
   102     ec_gen_device_t *gendev = *((ec_gen_device_t **) netdev_priv(dev));
       
   103     return ec_gen_device_start_xmit(gendev, skb);
       
   104 }
       
   105 
       
   106 /*****************************************************************************/
       
   107 
       
   108 void ec_gen_poll(struct net_device *dev)
       
   109 {
       
   110 }
       
   111 
       
   112 /*****************************************************************************/
       
   113 
       
   114 static const struct net_device_ops ec_gen_netdev_ops = {
       
   115 	.ndo_open		= ec_gen_netdev_open,
       
   116 	.ndo_stop		= ec_gen_netdev_stop,
       
   117 	.ndo_start_xmit	= ec_gen_netdev_start_xmit,
       
   118 };
       
   119 
       
   120 /*****************************************************************************/
       
   121 
       
   122 /** Init generic device.
       
   123  */
       
   124 int ec_gen_device_init(
       
   125         ec_gen_device_t *dev,
       
   126         struct net_device *real_netdev
       
   127         )
       
   128 {
       
   129     ec_gen_device_t **priv;
       
   130     char null = 0x00;
       
   131 
       
   132     dev->ecdev = NULL;
       
   133 #if 0
       
   134     dev->real_netdev = real_netdev;
       
   135 #endif
       
   136 
       
   137 	dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null, ether_setup);
       
   138 	if (!dev->netdev) {
       
   139 		return -ENOMEM;
       
   140 	}
       
   141     memcpy(dev->netdev->dev_addr, real_netdev->dev_addr, ETH_ALEN);
       
   142     dev->netdev->netdev_ops = &ec_gen_netdev_ops;
       
   143     priv = netdev_priv(dev->netdev);
       
   144     *priv = dev;
       
   145 
       
   146     return 0;
       
   147 }
       
   148 
       
   149 /*****************************************************************************/
       
   150 
       
   151 /** Clear generic device.
       
   152  */
       
   153 void ec_gen_device_clear(
       
   154         ec_gen_device_t *dev
       
   155         )
       
   156 {
       
   157     if (dev->ecdev) {
       
   158         ecdev_close(dev->ecdev);
       
   159         ecdev_withdraw(dev->ecdev);
       
   160     }
       
   161     free_netdev(dev->netdev);
       
   162 }
       
   163 
       
   164 /*****************************************************************************/
       
   165 
       
   166 /** Offer generic device to master.
       
   167  */
       
   168 int ec_gen_device_offer(
       
   169         ec_gen_device_t *dev
       
   170         )
       
   171 {
       
   172     int ret = 0;
       
   173 
       
   174 	dev->ecdev = ecdev_offer(dev->netdev, ec_gen_poll, THIS_MODULE);
       
   175     if (dev->ecdev) {
       
   176         if (ecdev_open(dev->ecdev)) {
       
   177             ecdev_withdraw(dev->ecdev);
       
   178             dev->ecdev = NULL;
       
   179         } else {
       
   180             ret = 1;
       
   181         }
       
   182     }
       
   183 
       
   184     return ret;
       
   185 }
       
   186 
       
   187 /*****************************************************************************/
       
   188 
       
   189 /** Open the device.
       
   190  */
       
   191 int ec_gen_device_open(
       
   192         ec_gen_device_t *dev
       
   193         )
       
   194 {
       
   195     int ret = 0;
       
   196 
       
   197 #if 0
       
   198 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
       
   199     ret = dev->real_netdev->netdev_ops->ndo_open(dev->real_netdev);
       
   200 #else
       
   201     ret = dev->real_netdev->open(dev->real_netdev);
       
   202 #endif
       
   203 #endif
       
   204 
       
   205     return ret;
       
   206 }
       
   207 
       
   208 /*****************************************************************************/
       
   209 
       
   210 /** Stop the device.
       
   211  */
       
   212 int ec_gen_device_stop(
       
   213         ec_gen_device_t *dev
       
   214         )
       
   215 {
       
   216     int ret = 0;
       
   217 
       
   218 #if 0
       
   219 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
       
   220     ret = dev->real_netdev->netdev_ops->ndo_stop(dev->real_netdev);
       
   221 #else
       
   222     ret = dev->real_netdev->stop(dev->real_netdev);
       
   223 #endif
       
   224 #endif
       
   225 
       
   226     return ret;
       
   227 }
       
   228 
       
   229 /*****************************************************************************/
       
   230 
       
   231 int ec_gen_device_start_xmit(
       
   232         ec_gen_device_t *dev,
       
   233         struct sk_buff *skb
       
   234         )
       
   235 {
       
   236     return 0;
       
   237 }
       
   238 
       
   239 /*****************************************************************************/
       
   240 
       
   241 /** Offer device.
       
   242  */
       
   243 int offer_device(
       
   244         struct net_device *netdev
       
   245         )
       
   246 {
       
   247     ec_gen_device_t *gendev;
       
   248     int ret = 0;
       
   249 
       
   250     gendev = kmalloc(sizeof(ec_gen_device_t), GFP_KERNEL);
       
   251     if (!gendev) {
       
   252         return -ENOMEM;
       
   253     }
       
   254 
       
   255     ret = ec_gen_device_init(gendev, netdev);
       
   256     if (ret) {
       
   257         kfree(gendev);
       
   258         return ret;
       
   259     }
       
   260 
       
   261     if (ec_gen_device_offer(gendev)) {
       
   262         list_add_tail(&gendev->list, &generic_devices);
       
   263     } else {
       
   264         ec_gen_device_clear(gendev);
       
   265         kfree(gendev);
       
   266     }
       
   267 
       
   268     return ret;
       
   269 }
       
   270 
       
   271 /*****************************************************************************/
       
   272 
       
   273 /** Clear devices.
       
   274  */
       
   275 void clear_devices(void)
       
   276 {
       
   277     ec_gen_device_t *gendev, *next;
       
   278 
       
   279     list_for_each_entry_safe(gendev, next, &generic_devices, list) {
       
   280         list_del(&gendev->list);
       
   281         ec_gen_device_clear(gendev);
       
   282         kfree(gendev);
       
   283     }
       
   284 }
       
   285 
       
   286 /*****************************************************************************/
       
   287 
       
   288 /** Module initialization.
       
   289  *
       
   290  * Initializes \a master_count masters.
       
   291  * \return 0 on success, else < 0
       
   292  */
       
   293 int __init ec_gen_init_module(void)
       
   294 {
       
   295     int ret = 0;
       
   296     struct net_device *netdev;
       
   297 
       
   298     printk(KERN_INFO PFX "EtherCAT master generic Ethernet device module %s\n",
       
   299             EC_MASTER_VERSION);
       
   300 
       
   301     INIT_LIST_HEAD(&generic_devices);
       
   302 
       
   303     read_lock(&dev_base_lock);
       
   304     for_each_netdev(&init_net, netdev) {
       
   305         if (netdev->type != ARPHRD_ETHER)
       
   306             continue;
       
   307         ret = offer_device(netdev);
       
   308         if (ret) {
       
   309             read_unlock(&dev_base_lock);
       
   310             goto out_err;
       
   311         }
       
   312     }
       
   313     read_unlock(&dev_base_lock);
       
   314     return ret;
       
   315 
       
   316 out_err:
       
   317     clear_devices();
       
   318     return ret;
       
   319 }
       
   320 
       
   321 /*****************************************************************************/
       
   322 
       
   323 /** Module cleanup.
       
   324  *
       
   325  * Clears all master instances.
       
   326  */
       
   327 void __exit ec_gen_cleanup_module(void)
       
   328 {
       
   329     clear_devices();
       
   330     printk(KERN_INFO PFX "Unloading.\n");
       
   331 }
       
   332 
       
   333 /*****************************************************************************/
       
   334 
       
   335 /** \cond */
       
   336 
       
   337 module_init(ec_gen_init_module);
       
   338 module_exit(ec_gen_cleanup_module);
       
   339 
       
   340 /** \endcond */
       
   341 
       
   342 /*****************************************************************************/