EoE net_device implementation.
authorFlorian Pose <fp@igh-essen.com>
Tue, 25 Apr 2006 11:39:33 +0000
changeset 203 c1f305e339c6
parent 202 d5141123a5af
child 204 5ab50514d9b2
EoE net_device implementation.
master/ethernet.c
master/ethernet.h
master/master.c
--- a/master/ethernet.c	Tue Apr 25 11:37:05 2006 +0000
+++ b/master/ethernet.c	Tue Apr 25 11:39:33 2006 +0000
@@ -38,13 +38,61 @@
 /*****************************************************************************/
 
 /**
+   Contains the private data of an EoE net_device.
+*/
+
+typedef struct
+{
+    struct net_device_stats stats; /**< device statistics */
+    ec_eoe_t *eoe; /**< pointer to parent eoe object */
+}
+ec_eoedev_priv_t;
+
+/*****************************************************************************/
+
+void ec_eoedev_init(struct net_device *);
+int ec_eoedev_open(struct net_device *);
+int ec_eoedev_stop(struct net_device *);
+int ec_eoedev_tx(struct sk_buff *, struct net_device *);
+struct net_device_stats *ec_eoedev_stats(struct net_device *);
+
+/*****************************************************************************/
+
+/**
    EoE constructor.
 */
 
-void ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
-{
+int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
+{
+    ec_eoedev_priv_t *priv;
+    int result;
+
     eoe->slave = slave;
     eoe->rx_state = EC_EOE_IDLE;
+
+    if (!(eoe->dev =
+          alloc_netdev(sizeof(ec_eoedev_priv_t), "eoe%d", ec_eoedev_init))) {
+        EC_ERR("Unable to allocate net_device for EoE object!\n");
+        goto out_return;
+    }
+
+    // set EoE object reference
+    priv = netdev_priv(eoe->dev);
+    priv->eoe = eoe;
+
+    // connect the net_device to the kernel
+    if ((result = register_netdev(eoe->dev))) {
+        EC_ERR("Unable to register net_device: error %i\n", result);
+        goto out_free;
+    }
+
+    return 0;
+
+ out_free:
+    free_netdev(eoe->dev);
+    eoe->dev = NULL;
+ out_return:
+    return -1;
 }
 
 /*****************************************************************************/
@@ -55,6 +103,10 @@
 
 void ec_eoe_clear(ec_eoe_t *eoe)
 {
+    if (eoe->dev) {
+        unregister_netdev(eoe->dev);
+        free_netdev(eoe->dev);
+    }
 }
 
 /*****************************************************************************/
@@ -153,3 +205,85 @@
 }
 
 /*****************************************************************************/
+
+/**
+   Initializes a net_device structure for an EoE object.
+*/
+
+void ec_eoedev_init(struct net_device *dev /**< pointer to the net_device */)
+{
+    ec_eoedev_priv_t *priv;
+
+    // initialize net_device
+    ether_setup(dev);
+    dev->open = ec_eoedev_open;
+    dev->stop = ec_eoedev_stop;
+    dev->hard_start_xmit = ec_eoedev_tx;
+    dev->get_stats = ec_eoedev_stats;
+
+    // initialize private data
+    priv = netdev_priv(dev);
+    memset(priv, 0, sizeof(ec_eoedev_priv_t));
+}
+
+/*****************************************************************************/
+
+/**
+   Opens the virtual network device.
+*/
+
+int ec_eoedev_open(struct net_device *dev /**< EoE net_device */)
+{
+    ec_eoedev_priv_t *priv = netdev_priv(dev);
+    netif_start_queue(dev);
+    EC_INFO("%s (slave %i) opened.\n", dev->name,
+            priv->eoe->slave->ring_position);
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Stops the virtual network device.
+*/
+
+int ec_eoedev_stop(struct net_device *dev /**< EoE net_device */)
+{
+    ec_eoedev_priv_t *priv = netdev_priv(dev);
+    netif_stop_queue(dev);
+    EC_INFO("%s (slave %i) stopped.\n", dev->name,
+            priv->eoe->slave->ring_position);
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Transmits data via the virtual network device.
+*/
+
+int ec_eoedev_tx(struct sk_buff *skb, /**< transmit socket buffer */
+                 struct net_device *dev /**< EoE net_device */
+                 )
+{
+    ec_eoedev_priv_t *priv = netdev_priv(dev);
+    priv->stats.tx_packets++;
+    dev_kfree_skb(skb);
+    EC_INFO("EoE device sent %i octets.\n", skb->len);
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Gets statistics about the virtual network device.
+*/
+
+struct net_device_stats *ec_eoedev_stats(struct net_device *dev
+                                         /**< EoE net_device */)
+{
+    ec_eoedev_priv_t *priv = netdev_priv(dev);
+    return &priv->stats;
+}
+
+/*****************************************************************************/
--- a/master/ethernet.h	Tue Apr 25 11:37:05 2006 +0000
+++ b/master/ethernet.h	Tue Apr 25 11:39:33 2006 +0000
@@ -29,6 +29,7 @@
 /*****************************************************************************/
 
 #include <linux/list.h>
+#include <linux/netdevice.h>
 
 #include "../include/ecrt.h"
 #include "globals.h"
@@ -62,12 +63,13 @@
     struct list_head list; /**< list item */
     ec_slave_t *slave; /**< pointer to the corresponding slave */
     ec_eoe_state_t rx_state; /**< state of the state machine */
+    struct net_device *dev; /**< net_device for virtual ethernet device */
 }
 ec_eoe_t;
 
 /*****************************************************************************/
 
-void ec_eoe_init(ec_eoe_t *, ec_slave_t *);
+int ec_eoe_init(ec_eoe_t *, ec_slave_t *);
 void ec_eoe_clear(ec_eoe_t *);
 void ec_eoe_run(ec_eoe_t *);
 void ec_eoe_print(const ec_eoe_t *);
--- a/master/master.c	Tue Apr 25 11:37:05 2006 +0000
+++ b/master/master.c	Tue Apr 25 11:39:33 2006 +0000
@@ -574,7 +574,10 @@
                 goto out_free;
             }
 
-            ec_eoe_init(eoe, slave);
+            if (ec_eoe_init(eoe, slave)) {
+                kfree(eoe);
+                goto out_free;
+            }
             list_add_tail(&eoe->list, &master->eoe_slaves);
         }
     }