EoE frame receiving; regarding open/stop commands.
authorFlorian Pose <fp@igh-essen.com>
Wed, 26 Apr 2006 16:43:01 +0000
changeset 210 1cc6bcb1e6ae
parent 209 fe044345aaec
child 211 c684b6b7adaf
EoE frame receiving; regarding open/stop commands.
master/ethernet.c
master/ethernet.h
--- a/master/ethernet.c	Wed Apr 26 12:12:57 2006 +0000
+++ b/master/ethernet.c	Wed Apr 26 16:43:01 2006 +0000
@@ -28,6 +28,8 @@
 
 /*****************************************************************************/
 
+#include <linux/etherdevice.h>
+
 #include "../include/ecrt.h"
 #include "globals.h"
 #include "master.h"
@@ -55,6 +57,7 @@
 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 *);
+void ec_eoedev_rx(struct net_device *, const uint8_t *, size_t);
 
 /*****************************************************************************/
 
@@ -69,6 +72,7 @@
 
     eoe->slave = slave;
     eoe->rx_state = EC_EOE_IDLE;
+    eoe->opened = 0;
 
     if (!(eoe->dev =
           alloc_netdev(sizeof(ec_eoedev_priv_t), "eoe%d", ec_eoedev_init))) {
@@ -120,11 +124,10 @@
     uint8_t *data;
     ec_master_t *master;
     size_t rec_size;
-    unsigned int i;
-    uint8_t fragment_number;
-    uint8_t complete_size;
-    uint8_t frame_number;
-    uint8_t last_fragment;
+    uint8_t fragment_number, frame_number, last_fragment, time_appended;
+    uint8_t fragment_offset, frame_type;
+
+    if (!eoe->opened) return;
 
     master = eoe->slave->master;
 
@@ -163,25 +166,44 @@
             return;
         }
 
-        fragment_number = EC_READ_U16(data + 2) & 0x003F;
-        complete_size = (EC_READ_U16(data + 2) >> 6) & 0x003F;
-        frame_number = (EC_READ_U16(data + 2) >> 12) & 0x0003;
-        last_fragment = (EC_READ_U16(data + 2) >> 15) & 0x0001;
-
-        EC_DBG("EOE %s received, fragment: %i, complete size: %i (0x%02X),"
-               " frame %i%s\n",
-               fragment_number ? "fragment" : "initiate", fragment_number,
-               (complete_size - 31) / 32, complete_size, frame_number,
-               last_fragment ? ", last fragment" : "");
-        EC_DBG("");
-        for (i = 0; i < rec_size - 2; i++) {
-            printk("%02X ", data[i + 2]);
-            if ((i + 1) % 16 == 0) {
-                printk("\n");
-                EC_DBG("");
+        frame_type = EC_READ_U16(data) & 0x000F;
+
+        if (frame_type == 0x00) { // EoE Fragment Request
+            last_fragment = (EC_READ_U16(data) >> 8) & 0x0001;
+            time_appended = (EC_READ_U16(data) >> 9) & 0x0001;
+            fragment_number = EC_READ_U16(data + 2) & 0x003F;
+            fragment_offset = (EC_READ_U16(data + 2) >> 6) & 0x003F;
+            frame_number = (EC_READ_U16(data + 2) >> 12) & 0x000F;
+
+#if 0
+            EC_DBG("EOE fragment req received, fragment: %i, offset: %i,"
+                   " frame %i%s%s, %i bytes\n", fragment_number,
+                   fragment_offset, frame_number,
+                   last_fragment ? ", last fragment" : "",
+                   time_appended ? ", + timestamp" : "",
+                   time_appended ? rec_size - 8 : rec_size - 4);
+
+#if 0
+            EC_DBG("");
+            for (i = 0; i < rec_size - 4; i++) {
+                printk("%02X ", data[i + 4]);
+                if ((i + 1) % 16 == 0) {
+                    printk("\n");
+                    EC_DBG("");
+                }
             }
-        }
-        printk("\n");
+            printk("\n");
+#endif
+#endif
+
+            ec_eoedev_rx(eoe->dev, data + 4,
+                         time_appended ? rec_size - 8 : rec_size - 4);
+        }
+        else {
+#if 1
+            EC_DBG("other frame received.\n");
+#endif
+        }
 
         eoe->rx_state = EC_EOE_IDLE;
         return;
@@ -198,6 +220,8 @@
 {
     EC_INFO("  EoE slave %i\n", eoe->slave->ring_position);
     EC_INFO("    RX State %i\n", eoe->rx_state);
+    EC_INFO("    Assigned device: %s (%s)\n", eoe->dev->name,
+            eoe->opened ? "opened" : "closed");
 }
 
 /*****************************************************************************/
@@ -209,6 +233,7 @@
 void ec_eoedev_init(struct net_device *dev /**< pointer to the net_device */)
 {
     ec_eoedev_priv_t *priv;
+    unsigned int i;
 
     // initialize net_device
     ether_setup(dev);
@@ -217,6 +242,8 @@
     dev->hard_start_xmit = ec_eoedev_tx;
     dev->get_stats = ec_eoedev_stats;
 
+    for (i = 0; i < 6; i++) dev->dev_addr[i] = (i + 1) | (i + 1) << 4;
+
     // initialize private data
     priv = netdev_priv(dev);
     memset(priv, 0, sizeof(ec_eoedev_priv_t));
@@ -231,6 +258,7 @@
 int ec_eoedev_open(struct net_device *dev /**< EoE net_device */)
 {
     ec_eoedev_priv_t *priv = netdev_priv(dev);
+    priv->eoe->opened = 1;
     netif_start_queue(dev);
     EC_INFO("%s (slave %i) opened.\n", dev->name,
             priv->eoe->slave->ring_position);
@@ -247,6 +275,7 @@
 {
     ec_eoedev_priv_t *priv = netdev_priv(dev);
     netif_stop_queue(dev);
+    priv->eoe->opened = 0;
     EC_INFO("%s (slave %i) stopped.\n", dev->name,
             priv->eoe->slave->ring_position);
     return 0;
@@ -272,6 +301,44 @@
 /*****************************************************************************/
 
 /**
+   Receives data from the bus and passes it to the network stack.
+*/
+
+void ec_eoedev_rx(struct net_device *dev, /**< EoE net_device */
+                 const uint8_t *data, /**< pointer to the data */
+                 size_t size /**< size of the received data */
+                 )
+{
+    ec_eoedev_priv_t *priv = netdev_priv(dev);
+    struct sk_buff *skb;
+
+    // allocate socket buffer
+    if (!(skb = dev_alloc_skb(size + 2))) {
+        if (printk_ratelimit())
+            EC_WARN("EoE RX: low on mem. frame dropped.\n");
+        priv->stats.rx_dropped++;
+        return;
+    }
+
+    // copy received data to socket buffer
+    memcpy(skb_put(skb, size), data, size);
+
+    // set socket buffer fields
+    skb->dev = dev;
+    skb->protocol = eth_type_trans(skb, dev);
+    skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+    // update statistics
+    priv->stats.rx_packets++;
+    priv->stats.rx_bytes += size;
+
+    // pass socket buffer to network stack
+    netif_rx(skb);
+}
+
+/*****************************************************************************/
+
+/**
    Gets statistics about the virtual network device.
 */
 
--- a/master/ethernet.h	Wed Apr 26 12:12:57 2006 +0000
+++ b/master/ethernet.h	Wed Apr 26 16:43:01 2006 +0000
@@ -64,6 +64,7 @@
     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 */
+    uint8_t opened; /**< net_device is opened */
 }
 ec_eoe_t;