devices/rtdmnet.c
branchstable-1.5
changeset 2709 e0c2f17ebed1
child 2711 a5c4ccc02285
equal deleted inserted replaced
2708:742c70a97622 2709:e0c2f17ebed1
       
     1 /******************************************************************************
       
     2  *
       
     3  *  $Id$
       
     4  *
       
     5  *  Copyright (C) 2006-2008  Florian Pose, Ingenieurgemeinschaft IgH
       
     6  *  Copyright (C) 2014-2018  Edouard Tisserant
       
     7  *
       
     8  *  This file is part of the IgH EtherCAT Master.
       
     9  *
       
    10  *  The IgH EtherCAT Master is free software; you can redistribute it and/or
       
    11  *  modify it under the terms of the GNU General Public License version 2, as
       
    12  *  published by the Free Software Foundation.
       
    13  *
       
    14  *  The IgH EtherCAT Master is distributed in the hope that it will be useful,
       
    15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
       
    17  *  Public License for more details.
       
    18  *
       
    19  *  You should have received a copy of the GNU General Public License along
       
    20  *  with the IgH EtherCAT Master; if not, write to the Free Software
       
    21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    22  *
       
    23  *  ---
       
    24  *
       
    25  *  The license mentioned above concerns the source code only. Using the
       
    26  *  EtherCAT technology and brand is only permitted in compliance with the
       
    27  *  industrial property and similar rights of Beckhoff Automation GmbH.
       
    28  *
       
    29  *****************************************************************************/
       
    30 
       
    31 /** \file
       
    32  * EtherCAT generic Xenomai's RTDM RAW Ethernet socket device module.
       
    33  * Heavily based on generic.c. Should be merged in a single file with #ifdefs
       
    34  */
       
    35 
       
    36 /*****************************************************************************/
       
    37 
       
    38 #include <linux/module.h>
       
    39 #include <linux/device.h>
       
    40 #include <linux/err.h>
       
    41 #include <linux/version.h>
       
    42 #include <linux/if_arp.h> /* ARPHRD_ETHER */
       
    43 #include <linux/etherdevice.h>
       
    44 #include <rtdm/rtdm.h>
       
    45 
       
    46 // for rtnetif_carrier_ok
       
    47 // This needs -I@XENOMAI_DIR@/kernel/drivers/net/stack/include in Kbuild.in
       
    48 #include <rtnet_port.h>
       
    49 
       
    50 #include "../globals.h"
       
    51 #include "ecdev.h"
       
    52 
       
    53 #define PFX "ec_rtnet: "
       
    54 
       
    55 #define ETH_P_ETHERCAT 0x88A4
       
    56 
       
    57 #define EC_GEN_RX_BUF_SIZE 1600
       
    58 
       
    59 /*****************************************************************************/
       
    60 
       
    61 int __init ec_gen_init_module(void);
       
    62 void __exit ec_gen_cleanup_module(void);
       
    63 
       
    64 /*****************************************************************************/
       
    65 
       
    66 /** \cond */
       
    67 
       
    68 MODULE_AUTHOR("Edouard Tisserant <edouard.tisserant@gmail.com>");
       
    69 MODULE_DESCRIPTION("EtherCAT generic Xenomai's RTDM RAW Ethernet socket device module.");
       
    70 MODULE_LICENSE("GPL");
       
    71 MODULE_VERSION(EC_MASTER_VERSION);
       
    72 
       
    73 /** \endcond */
       
    74 
       
    75 struct list_head generic_devices;
       
    76 
       
    77 typedef struct {
       
    78     struct list_head list;
       
    79     struct net_device *netdev;
       
    80     struct rtnet_device *used_netdev;
       
    81     int socket;
       
    82     ec_device_t *ecdev;
       
    83     uint8_t *rx_buf;
       
    84     // struct sockaddr_ll dest_addr;
       
    85 } ec_gen_device_t;
       
    86 
       
    87 typedef struct {
       
    88     struct list_head list;
       
    89     struct rtnet_device *netdev;
       
    90     char name[IFNAMSIZ];
       
    91     int ifindex;
       
    92     uint8_t dev_addr[ETH_ALEN];
       
    93 } ec_gen_interface_desc_t;
       
    94 
       
    95 int ec_gen_device_open(ec_gen_device_t *);
       
    96 int ec_gen_device_stop(ec_gen_device_t *);
       
    97 int ec_gen_device_start_xmit(ec_gen_device_t *, struct sk_buff *);
       
    98 void ec_gen_device_poll(ec_gen_device_t *);
       
    99 
       
   100 /*****************************************************************************/
       
   101 
       
   102 static int ec_gen_netdev_open(struct net_device *dev)
       
   103 {
       
   104     ec_gen_device_t *gendev = *((ec_gen_device_t **) netdev_priv(dev));
       
   105     return ec_gen_device_open(gendev);
       
   106 }
       
   107 
       
   108 /*****************************************************************************/
       
   109 
       
   110 static int ec_gen_netdev_stop(struct net_device *dev)
       
   111 {
       
   112     ec_gen_device_t *gendev = *((ec_gen_device_t **) netdev_priv(dev));
       
   113     return ec_gen_device_stop(gendev);
       
   114 }
       
   115 
       
   116 /*****************************************************************************/
       
   117 
       
   118 static int ec_gen_netdev_start_xmit(
       
   119         struct sk_buff *skb,
       
   120         struct net_device *dev
       
   121         )
       
   122 {
       
   123     ec_gen_device_t *gendev = *((ec_gen_device_t **) netdev_priv(dev));
       
   124     return ec_gen_device_start_xmit(gendev, skb);
       
   125 }
       
   126 
       
   127 /*****************************************************************************/
       
   128 
       
   129 void ec_gen_poll(struct net_device *dev)
       
   130 {
       
   131     ec_gen_device_t *gendev = *((ec_gen_device_t **) netdev_priv(dev));
       
   132     ec_gen_device_poll(gendev);
       
   133 }
       
   134 
       
   135 /*****************************************************************************/
       
   136 
       
   137 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
       
   138 static const struct net_device_ops ec_gen_netdev_ops = {
       
   139     .ndo_open       = ec_gen_netdev_open,
       
   140     .ndo_stop       = ec_gen_netdev_stop,
       
   141     .ndo_start_xmit = ec_gen_netdev_start_xmit,
       
   142 };
       
   143 #endif
       
   144 
       
   145 /*****************************************************************************/
       
   146 
       
   147 /** Init generic device.
       
   148  */
       
   149 int ec_gen_device_init(
       
   150         ec_gen_device_t *dev
       
   151         )
       
   152 {
       
   153     ec_gen_device_t **priv;
       
   154     char null = 0x00;
       
   155 
       
   156     dev->ecdev = NULL;
       
   157     dev->socket = -1;
       
   158     dev->rx_buf = NULL;
       
   159 
       
   160 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
       
   161     dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null,
       
   162             NET_NAME_UNKNOWN, ether_setup);
       
   163 #else
       
   164     dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null, ether_setup);
       
   165 #endif
       
   166     if (!dev->netdev) {
       
   167         return -ENOMEM;
       
   168     }
       
   169 
       
   170 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
       
   171     dev->netdev->netdev_ops = &ec_gen_netdev_ops;
       
   172 #else
       
   173     dev->netdev->open = ec_gen_netdev_open;
       
   174     dev->netdev->stop = ec_gen_netdev_stop;
       
   175     dev->netdev->hard_start_xmit = ec_gen_netdev_start_xmit;
       
   176 #endif
       
   177 
       
   178     priv = netdev_priv(dev->netdev);
       
   179     *priv = dev;
       
   180 
       
   181     return 0;
       
   182 }
       
   183 
       
   184 /*****************************************************************************/
       
   185 
       
   186 /** Clear generic device.
       
   187  */
       
   188 void ec_gen_device_clear(
       
   189         ec_gen_device_t *dev
       
   190         )
       
   191 {
       
   192     if (dev->ecdev) {
       
   193         ecdev_close(dev->ecdev);
       
   194         ecdev_withdraw(dev->ecdev);
       
   195     }
       
   196     if (!(dev->socket < 0)) {
       
   197         rtdm_close(dev->socket);
       
   198         dev->socket = -1;
       
   199     }
       
   200     free_netdev(dev->netdev);
       
   201 
       
   202     if (dev->rx_buf) {
       
   203         kfree(dev->rx_buf);
       
   204     }
       
   205 }
       
   206 
       
   207 /*****************************************************************************/
       
   208 
       
   209 /** Creates a network socket.
       
   210  */
       
   211 int ec_gen_device_create_socket(
       
   212         ec_gen_device_t *dev,
       
   213         ec_gen_interface_desc_t *desc
       
   214         )
       
   215 {
       
   216     int ret;
       
   217     struct sockaddr_ll sa;
       
   218 
       
   219     dev->rx_buf = kmalloc(EC_GEN_RX_BUF_SIZE, GFP_KERNEL);
       
   220     if (!dev->rx_buf) {
       
   221         return -ENOMEM;
       
   222     }
       
   223 
       
   224     /* create rt-socket */
       
   225     dev->socket = rtdm_socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ETHERCAT));
       
   226     if (dev->socket < 0) {
       
   227         printk(" rtdm_socket() = %d!\n", dev->socket);
       
   228         return dev->socket;
       
   229     }
       
   230 
       
   231     printk(KERN_ERR PFX "Binding socket to interface %i (%s).\n",
       
   232             desc->ifindex, desc->name);
       
   233 
       
   234     memset(&sa, 0x00, sizeof(sa));
       
   235     sa.sll_family = AF_PACKET;
       
   236     sa.sll_protocol = htons(ETH_P_ETHERCAT);
       
   237     sa.sll_ifindex = desc->ifindex;
       
   238     ret = rtdm_bind(dev->socket, (struct sockaddr *)&sa,
       
   239                       sizeof(struct sockaddr_ll));
       
   240     if (ret < 0) {
       
   241         printk(" rtdm_bind() = %d!\n", ret);
       
   242         rtdm_close(dev->socket);
       
   243         dev->socket = -1;
       
   244         return ret;
       
   245     }
       
   246 
       
   247     return 0;
       
   248 }
       
   249 
       
   250 /*****************************************************************************/
       
   251 
       
   252 /** Offer generic device to master.
       
   253  */
       
   254 int ec_gen_device_offer(
       
   255         ec_gen_device_t *dev,
       
   256         ec_gen_interface_desc_t *desc
       
   257         )
       
   258 {
       
   259     int ret = 0;
       
   260 
       
   261     dev->used_netdev = desc->netdev;
       
   262     memcpy(dev->netdev->dev_addr, desc->dev_addr, ETH_ALEN);
       
   263 
       
   264     dev->ecdev = ecdev_offer(dev->netdev, ec_gen_poll, THIS_MODULE);
       
   265     if (dev->ecdev) {
       
   266         if (ec_gen_device_create_socket(dev, desc)) {
       
   267             ecdev_withdraw(dev->ecdev);
       
   268             dev->ecdev = NULL;
       
   269         } else if (ecdev_open(dev->ecdev)) {
       
   270             ecdev_withdraw(dev->ecdev);
       
   271             dev->ecdev = NULL;
       
   272         } else {
       
   273             ecdev_set_link(dev->ecdev, rtnetif_carrier_ok(dev->used_netdev)); // FIXME
       
   274             ret = 1;
       
   275         }
       
   276     }
       
   277 
       
   278     return ret;
       
   279 }
       
   280 
       
   281 /*****************************************************************************/
       
   282 
       
   283 /** Open the device.
       
   284  */
       
   285 int ec_gen_device_open(
       
   286         ec_gen_device_t *dev
       
   287         )
       
   288 {
       
   289     return 0;
       
   290 }
       
   291 
       
   292 /*****************************************************************************/
       
   293 
       
   294 /** Stop the device.
       
   295  */
       
   296 int ec_gen_device_stop(
       
   297         ec_gen_device_t *dev
       
   298         )
       
   299 {
       
   300     return 0;
       
   301 }
       
   302 
       
   303 /*****************************************************************************/
       
   304 
       
   305 int ec_gen_device_start_xmit(
       
   306         ec_gen_device_t *dev,
       
   307         struct sk_buff *skb
       
   308         )
       
   309 {
       
   310     struct user_msghdr msg;
       
   311     struct iovec iov;
       
   312     size_t len = skb->len;
       
   313     int ret;
       
   314 
       
   315     ecdev_set_link(dev->ecdev, rtnetif_carrier_ok(dev->used_netdev));
       
   316     //ecdev_set_link(dev->ecdev, 1); // FIXME
       
   317 
       
   318     iov.iov_base = skb->data;
       
   319     iov.iov_len = len;
       
   320     memset(&msg, 0, sizeof(msg));
       
   321     // msg.msg_name    = &dev->dest_addr;
       
   322     // msg.msg_namelen = sizeof(dev->dest_addr);
       
   323     msg.msg_iov     = &iov;
       
   324     msg.msg_iovlen  = 1;
       
   325 
       
   326     ret = rtdm_sendmsg(dev->socket, &msg, 0);
       
   327     // printk("sendmsg: %d\n", ret);
       
   328     // if (ret != len && ret != -ENOSYS)
       
   329     //     printk(" rtdm_sendmsg() = %d!\n", ret);
       
   330 
       
   331     return ret == len ? NETDEV_TX_OK : NETDEV_TX_BUSY;
       
   332 }
       
   333 
       
   334 /*****************************************************************************/
       
   335 
       
   336 /** Polls the device.
       
   337  */
       
   338 void ec_gen_device_poll(
       
   339         ec_gen_device_t *dev
       
   340         )
       
   341 {
       
   342     struct user_msghdr msg;
       
   343     struct iovec iov;
       
   344     int ret, budget = 128; // FIXME
       
   345 
       
   346     ecdev_set_link(dev->ecdev, rtnetif_carrier_ok(dev->used_netdev));
       
   347 
       
   348     do {
       
   349         iov.iov_base = dev->rx_buf;
       
   350         iov.iov_len = EC_GEN_RX_BUF_SIZE;
       
   351         memset(&msg, 0, sizeof(msg));
       
   352         msg.msg_iov     = &iov;
       
   353         msg.msg_iovlen  = 1;
       
   354 
       
   355         ret = rtdm_recvmsg(dev->socket, &msg, MSG_DONTWAIT);
       
   356         if (ret > 0) {
       
   357             ecdev_receive(dev->ecdev, dev->rx_buf, ret);
       
   358         } else if (ret < 0) {
       
   359             break;
       
   360         }
       
   361         //printk("revmsg: %d\n", ret);
       
   362         budget--;
       
   363     } while (budget);
       
   364 }
       
   365 
       
   366 /*****************************************************************************/
       
   367 
       
   368 /** Offer device.
       
   369  */
       
   370 int offer_device(
       
   371         ec_gen_interface_desc_t *desc
       
   372         )
       
   373 {
       
   374     ec_gen_device_t *gendev;
       
   375     int ret = 0;
       
   376 
       
   377     gendev = kmalloc(sizeof(ec_gen_device_t), GFP_KERNEL);
       
   378     if (!gendev) {
       
   379         return -ENOMEM;
       
   380     }
       
   381 
       
   382     ret = ec_gen_device_init(gendev);
       
   383     if (ret) {
       
   384         kfree(gendev);
       
   385         return ret;
       
   386     }
       
   387 
       
   388     if (ec_gen_device_offer(gendev, desc)) {
       
   389         list_add_tail(&gendev->list, &generic_devices);
       
   390     } else {
       
   391         ec_gen_device_clear(gendev);
       
   392         kfree(gendev);
       
   393     }
       
   394 
       
   395     return ret;
       
   396 }
       
   397 
       
   398 /*****************************************************************************/
       
   399 
       
   400 /** Clear devices.
       
   401  */
       
   402 void clear_devices(void)
       
   403 {
       
   404     ec_gen_device_t *gendev, *next;
       
   405 
       
   406     list_for_each_entry_safe(gendev, next, &generic_devices, list) {
       
   407         list_del(&gendev->list);
       
   408         ec_gen_device_clear(gendev);
       
   409         kfree(gendev);
       
   410     }
       
   411 }
       
   412 
       
   413 /*****************************************************************************/
       
   414 
       
   415 /** Module initialization.
       
   416  *
       
   417  * Initializes \a master_count masters.
       
   418  * \return 0 on success, else < 0
       
   419  */
       
   420 int __init ec_gen_init_module(void)
       
   421 {
       
   422     int ret = 0;
       
   423     int devices = 0;
       
   424     int i;
       
   425     struct list_head descs;
       
   426     struct rtnet_device *rtdev;
       
   427     ec_gen_interface_desc_t *desc, *next;
       
   428 
       
   429     printk(KERN_INFO PFX "EtherCAT master RTnet Ethernet device module %s\n",
       
   430             EC_MASTER_VERSION);
       
   431 
       
   432     INIT_LIST_HEAD(&generic_devices);
       
   433     INIT_LIST_HEAD(&descs);
       
   434 
       
   435     for (i = 0; i < MAX_RT_DEVICES; i++) {
       
   436 
       
   437         rtdev = rtdev_get_by_index(i);
       
   438         if (rtdev != NULL) {
       
   439             mutex_lock(&rtdev->nrt_lock);
       
   440 
       
   441             //if (test_bit(PRIV_FLAG_UP, &rtdev->priv_flags)) {
       
   442             //    mutex_unlock(&rtdev->nrt_lock);
       
   443             //    printk(KERN_ERR PFX "%s busy, skipping device!\n", rtdev->name);
       
   444             //    rtdev_dereference(rtdev);
       
   445             //    continue;
       
   446             //}
       
   447 
       
   448             desc = kmalloc(sizeof(ec_gen_interface_desc_t), GFP_ATOMIC);
       
   449             if (!desc) {
       
   450                 ret = -ENOMEM;
       
   451                 goto out_err;
       
   452             }
       
   453             strncpy(desc->name, rtdev->name, IFNAMSIZ);
       
   454             desc->netdev = rtdev;
       
   455             desc->ifindex = rtdev->ifindex;
       
   456             memcpy(desc->dev_addr, rtdev->dev_addr, ETH_ALEN);
       
   457             list_add_tail(&desc->list, &descs);
       
   458               mutex_unlock(&rtdev->nrt_lock);
       
   459 
       
   460             devices++;
       
   461         }
       
   462     }
       
   463 
       
   464     if (devices == 0) {
       
   465         printk(KERN_ERR PFX "no real-time devices found!\n");
       
   466         ret = -ENODEV;
       
   467         goto out_err;
       
   468     }
       
   469 
       
   470     list_for_each_entry_safe(desc, next, &descs, list) {
       
   471         ret = offer_device(desc);
       
   472         if (ret) {
       
   473             goto out_err;
       
   474         }
       
   475         kfree(desc);
       
   476     }
       
   477     return ret;
       
   478 
       
   479 out_err:
       
   480     list_for_each_entry_safe(desc, next, &descs, list) {
       
   481         list_del(&desc->list);
       
   482         kfree(desc);
       
   483     }
       
   484     clear_devices();
       
   485     return ret;
       
   486 }
       
   487 
       
   488 /*****************************************************************************/
       
   489 
       
   490 /** Module cleanup.
       
   491  *
       
   492  * Clears all master instances.
       
   493  */
       
   494 void __exit ec_gen_cleanup_module(void)
       
   495 {
       
   496     clear_devices();
       
   497     printk(KERN_INFO PFX "Unloading.\n");
       
   498 }
       
   499 
       
   500 /*****************************************************************************/
       
   501 
       
   502 /** \cond */
       
   503 
       
   504 module_init(ec_gen_init_module);
       
   505 module_exit(ec_gen_cleanup_module);
       
   506 
       
   507 /** \endcond */
       
   508 
       
   509 /*****************************************************************************/