Prepared Free-Run mode
authorFlorian Pose <fp@igh-essen.com>
Wed, 12 Apr 2006 10:40:32 +0000
changeset 191 ca805255a935
parent 190 4e32bcc6b361
child 192 8d7bd5082ed5
Prepared Free-Run mode
devices/8139too.c
devices/Makefile
devices/ecdev.h
master/Makefile
master/device.c
master/master.c
master/master.h
master/module.c
rt/msr_rt.c
--- a/devices/8139too.c	Tue Apr 11 14:39:17 2006 +0000
+++ b/devices/8139too.c	Wed Apr 12 10:40:32 2006 +0000
@@ -199,15 +199,10 @@
 
 /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-// Uncomment for debugging
-//#define EC_DEBUG
-
-// Device index for EtherCAT device selection
 static int ec_device_index = -1;
 static int ec_device_master_index = 0;
-
 static ec_device_t *rtl_ec_dev;
-int rtl_ec_dev_registered = 0;
+struct net_device *rtl_ec_net_dev = NULL;
 
 /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
 
@@ -1025,13 +1020,9 @@
 
 	/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-	if (board_idx == ec_device_index)
-    {
-          printk(KERN_INFO "Registering EtherCAT device...\n");
-          rtl_ec_dev = ecdev_register(ec_device_master_index, dev,
-                                             rtl8139_interrupt, THIS_MODULE);
-
-          if (rtl_ec_dev) strcpy(dev->name, "ec0");
+	if (board_idx == ec_device_index) {
+            rtl_ec_net_dev = dev;
+            strcpy(dev->name, "ec0");
 	}
 
 	/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -1092,7 +1083,7 @@
 	/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
 	/* EtherCAT-Karten nicht beim Stack anmelden. */
-    if (!ecdev_is_ec(rtl_ec_dev, dev))
+        if (dev != rtl_ec_net_dev)
 	{
                 DPRINTK("About to register device named %s (%p)...\n", dev->name, dev);
                 i = register_netdev (dev);
@@ -1190,7 +1181,7 @@
 
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-        if (!ecdev_is_ec(rtl_ec_dev, dev))
+        if (dev != rtl_ec_net_dev)
         {
                 unregister_netdev (dev);
 	}
@@ -1403,7 +1394,7 @@
         printk(KERN_DEBUG "%s: open\n", dev->name);
 #endif
 
-        if (!ecdev_is_ec(rtl_ec_dev, dev))
+        if (dev != rtl_ec_net_dev)
         {
                 retval = request_irq(dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev);
                 if (retval)
@@ -1420,7 +1411,7 @@
         {
                 /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-                if (!ecdev_is_ec(rtl_ec_dev, dev))
+                if (dev != rtl_ec_net_dev)
                 {
                           free_irq(dev->irq, dev);
                 }
@@ -1445,7 +1436,7 @@
 
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-        if (!ecdev_is_ec(rtl_ec_dev, dev))
+        if (dev != rtl_ec_net_dev)
         {
                 netif_start_queue (dev);
 
@@ -1471,7 +1462,7 @@
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
 
-        if (ecdev_is_ec(rtl_ec_dev, dev)) {
+        if (dev == rtl_ec_net_dev) {
             void __iomem *ioaddr = tp->mmio_addr;
             uint16_t state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS;
             ecdev_link_state(rtl_ec_dev, state ? 1 : 0);
@@ -1545,7 +1536,7 @@
 
 	/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-        if (!ecdev_is_ec(rtl_ec_dev, dev))
+        if (dev != rtl_ec_net_dev)
         {
                 /* Enable all known interrupts by setting the interrupt mask. */
                 RTL_W16 (IntrMask, rtl8139_intr_mask);
@@ -1814,7 +1805,7 @@
     /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
 
-        if (!ecdev_is_ec(rtl_ec_dev, dev))
+        if (dev != rtl_ec_net_dev)
         {
                 spin_lock(&tp->rx_lock);
 
@@ -1864,16 +1855,16 @@
                         memset(tp->tx_buf[entry], 0, ETH_ZLEN);
 
                 skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
-                if (!ecdev_is_ec(rtl_ec_dev, dev)) dev_kfree_skb(skb);
+                if (dev != rtl_ec_net_dev) dev_kfree_skb(skb);
 	}
         else
         {
-                if (!ecdev_is_ec(rtl_ec_dev, dev)) dev_kfree_skb(skb);
+                if (dev != rtl_ec_net_dev) dev_kfree_skb(skb);
                 tp->stats.tx_dropped++;
                 return 0;
 	}
 
-	if (!ecdev_is_ec(rtl_ec_dev, dev))
+	if (dev != rtl_ec_net_dev)
         {
                 spin_lock_irq(&tp->lock);
         }
@@ -1890,7 +1881,7 @@
 
 	/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-	if (!ecdev_is_ec(rtl_ec_dev, dev))
+	if (dev != rtl_ec_net_dev)
         {
                 if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
                         netif_stop_queue (dev);
@@ -1965,7 +1956,7 @@
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
 #ifndef RTL8139_NDEBUG
-	if (!ecdev_is_ec(rtl_ec_dev, dev) && tp->cur_tx - dirty_tx > NUM_TX_DESC) {
+	if (dev != rtl_ec_net_dev && tp->cur_tx - dirty_tx > NUM_TX_DESC) {
 		printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n",
 		        dev->name, dirty_tx, tp->cur_tx);
 		dirty_tx += NUM_TX_DESC;
@@ -1981,7 +1972,7 @@
 
                 /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-		if (!ecdev_is_ec(rtl_ec_dev, dev))
+		if (dev != rtl_ec_net_dev)
                 {
                         netif_wake_queue (dev);
                 }
@@ -2120,7 +2111,7 @@
 		 RTL_R16 (RxBufAddr),
 		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
 
-	while ((ecdev_is_ec(rtl_ec_dev, dev) || netif_running(dev))
+	while ((dev == rtl_ec_net_dev || netif_running(dev))
 	       && received < budget
 	       && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
 		u32 ring_offset = cur_rx % RX_BUF_LEN;
@@ -2137,7 +2128,7 @@
 
                 /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-		if (!ecdev_is_ec(rtl_ec_dev, dev) && netif_msg_rx_status(tp))
+		if (dev != rtl_ec_net_dev && netif_msg_rx_status(tp))
                         printk(KERN_DEBUG "%s:  rtl8139_rx() status %4.4x, size %4.4x,"
                                " cur %4.4x.\n", dev->name, rx_status,
                                rx_size, cur_rx);
@@ -2193,7 +2184,7 @@
 
                 /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-                if (!ecdev_is_ec(rtl_ec_dev, dev))
+                if (dev != rtl_ec_net_dev)
                 {
                         /* Malloc up new buffer, compatible with net-2e. */
                         /* Omit the four octet CRC from the length. */
@@ -2356,7 +2347,7 @@
 
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-	if (ecdev_is_ec(rtl_ec_dev, dev))
+	if (dev == rtl_ec_net_dev)
         {
                 status = RTL_R16 (IntrStatus);
 	}
@@ -2380,7 +2371,7 @@
 
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-	if (!ecdev_is_ec(rtl_ec_dev, dev))
+	if (dev != rtl_ec_net_dev)
         {
                 /* close possible race's with dev_close */
                 if (unlikely(!netif_running(dev))) {
@@ -2408,7 +2399,7 @@
 
 	if (status & RxAckBits)
         {
-          if (!ecdev_is_ec(rtl_ec_dev, dev))
+          if (dev != rtl_ec_net_dev)
           {
             /* Polling vormerken */
             if (netif_rx_schedule_prep(dev)) {
@@ -2438,7 +2429,7 @@
  out:
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-	if (!ecdev_is_ec(rtl_ec_dev, dev))
+	if (dev != rtl_ec_net_dev)
         {
           spin_unlock (&tp->lock);
         }
@@ -2472,7 +2463,7 @@
 
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-        if (!ecdev_is_ec(rtl_ec_dev, dev))
+        if (dev != rtl_ec_net_dev)
         {
                 netif_stop_queue(dev);
                 if (tp->thr_pid >= 0) {
@@ -2737,7 +2728,7 @@
 
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-	if (ecdev_is_ec(rtl_ec_dev, dev) || !netif_running(dev))
+	if (dev == rtl_ec_net_dev || !netif_running(dev))
 		return -EINVAL;
 
         /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -2758,7 +2749,7 @@
 
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-	if (ecdev_is_ec(rtl_ec_dev, dev) || netif_running(dev))
+	if (dev == rtl_ec_net_dev || netif_running(dev))
         {
                 spin_lock_irqsave (&tp->lock, flags);
                 tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
@@ -2845,7 +2836,7 @@
 
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-	if (ecdev_is_ec(rtl_ec_dev, dev) || !netif_running (dev))
+	if (dev == rtl_ec_net_dev || !netif_running (dev))
                 return 0;
 
         /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -2878,7 +2869,7 @@
 
         /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-	if (ecdev_is_ec(rtl_ec_dev, dev) || !netif_running (dev))
+	if (dev == rtl_ec_net_dev || !netif_running (dev))
                 return 0;
 
         /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -2907,58 +2898,64 @@
 
 static int __init rtl8139_init_module (void)
 {
-	/* when we're a module, we always print a version message,
-	 * even if no 8139 board is found.
-	 */
-#ifdef MODULE
-	printk (KERN_INFO RTL8139_DRIVER_NAME "\n");
-#endif
-
     /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
 
-    printk(KERN_INFO "Initializing RTL8139-EtherCAT module. %s\n", COMPILE_INFO);
-    printk(KERN_INFO "EtherCAT device index is %i.\n", ec_device_index);
-
-    if (pci_module_init(&rtl8139_pci_driver) < 0)
-    {
-      printk(KERN_ERR "Could not init PCI module.\n");
-      goto out_ec_dev;
+    printk(KERN_INFO RTL8139_DRIVER_NAME " " COMPILE_INFO "\n");
+    printk(KERN_INFO "ec_device_index is %i\n", ec_device_index);
+
+    if (pci_module_init(&rtl8139_pci_driver) < 0) {
+        printk(KERN_ERR "Failed to init PCI module.\n");
+        goto out_return;
     }
 
-    if (!rtl_ec_dev)
-    {
-      printk(KERN_WARNING "NO EtherCAT device registered!\n");
+    if (rtl_ec_net_dev) {
+        printk(KERN_INFO "Registering EtherCAT device...\n");
+        if (!(rtl_ec_dev = ecdev_register(ec_device_master_index,
+                                          rtl_ec_net_dev, rtl8139_interrupt,
+                                          THIS_MODULE))) {
+            printk(KERN_ERR "Failed to register EtherCAT device!\n");
+            goto out_pci;
+        }
+
+        printk(KERN_INFO "Starting EtherCAT device...\n");
+        if (ecdev_start(ec_device_master_index)) {
+            printk(KERN_ERR "Failed to start EtherCAT device!\n");
+            goto out_unregister;
+        }
     }
+    else {
+        printk(KERN_WARNING "NO EtherCAT device registered!\n");
+    }
 
     return 0;
 
- out_ec_dev:
-    if (rtl_ec_dev) {
-      printk(KERN_INFO "Unregistering RTL8139-EtherCAT device...\n");
+ out_unregister:
+    ecdev_unregister(ec_device_master_index, rtl_ec_dev);
+ out_pci:
+    pci_unregister_driver(&rtl8139_pci_driver);
+ out_return:
+    return -1;
+
+    /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
+}
+
+
+static void __exit rtl8139_cleanup_module (void)
+{
+  /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+  printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n");
+
+  if (rtl_ec_net_dev) {
+      printk(KERN_INFO "Stopping device...\n");
+      ecdev_stop(ec_device_master_index);
+      printk(KERN_INFO "Unregistering device...\n");
       ecdev_unregister(ec_device_master_index, rtl_ec_dev);
       rtl_ec_dev = NULL;
-    }
-
-    return -1;
-
-    /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
-}
-
-
-static void __exit rtl8139_cleanup_module (void)
-{
-  /* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
-
-  printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n");
+  }
 
   pci_unregister_driver(&rtl8139_pci_driver);
 
-  if (rtl_ec_dev) {
-    printk(KERN_INFO "Unregistering RTL8139-EtherCAT device...\n");
-    ecdev_unregister(ec_device_master_index, rtl_ec_dev);
-    rtl_ec_dev = NULL;
-  }
-
   printk(KERN_INFO "RTL8139-EtherCAT module cleaned up.\n");
 
   /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
--- a/devices/Makefile	Tue Apr 11 14:39:17 2006 +0000
+++ b/devices/Makefile	Wed Apr 12 10:40:32 2006 +0000
@@ -17,9 +17,8 @@
 
 ec_8139too-objs := 8139too.o
 
-REV = `svnversion $(src)`
-DATE = `date`
-
+REV := $(shell svnversion $(src))
+DATE := $(shell date)
 EXTRA_CFLAGS = -DEC_REV="$(REV)" -DEC_USER="$(USER)" -DEC_DATE="$(DATE)"
 
 #------------------------------------------------------------------------------
--- a/devices/ecdev.h	Tue Apr 11 14:39:17 2006 +0000
+++ b/devices/ecdev.h	Wed Apr 12 10:40:32 2006 +0000
@@ -26,10 +26,12 @@
                             struct module *module);
 void ecdev_unregister(unsigned int master_index, ec_device_t *device);
 
+int ecdev_start(unsigned int master_index);
+void ecdev_stop(unsigned int master_index);
+
 /*****************************************************************************/
 // Device methods
 
-int ecdev_is_ec(const ec_device_t *device, const struct net_device *net_dev);
 void ecdev_receive(ec_device_t *device, const void *data, size_t size);
 void ecdev_link_state(ec_device_t *device, uint8_t newstate);
 
--- a/master/Makefile	Tue Apr 11 14:39:17 2006 +0000
+++ b/master/Makefile	Wed Apr 12 10:40:32 2006 +0000
@@ -33,7 +33,7 @@
 KERNEL := $(shell uname -r)
 endif
 
-KERNELDIR = /lib/modules/$(KERNEL)/build
+KERNELDIR := /lib/modules/$(KERNEL)/build
 
 modules:
 	$(MAKE) -C $(KERNELDIR) M=`pwd`
--- a/master/device.c	Tue Apr 11 14:39:17 2006 +0000
+++ b/master/device.c	Wed Apr 12 10:40:32 2006 +0000
@@ -197,21 +197,6 @@
  *****************************************************************************/
 
 /**
-   Prüft, ob das Net-Device \a dev zum registrierten EtherCAT-Gerät gehört.
-
-   \return 0 wenn nein, nicht-null wenn ja.
-*/
-
-inline int ecdev_is_ec(const ec_device_t *device,  /**< EtherCAT-Gerät */
-                const struct net_device *dev /**< Net-Device */
-                )
-{
-    return device && device->dev == dev;
-}
-
-/*****************************************************************************/
-
-/**
    Nimmt einen Empfangenen Rahmen entgegen.
 
    Kopiert die empfangenen Daten in den Receive-Buffer.
@@ -240,6 +225,11 @@
                       uint8_t state /**< Verbindungszustand */
                       )
 {
+    if (unlikely(!device)) {
+        EC_WARN("ecdev_link_state: no device!\n");
+        return;
+    }
+
     if (likely(state != device->link_state)) {
         device->link_state = state;
         EC_INFO("Link state changed to %s.\n", (state ? "UP" : "DOWN"));
@@ -248,7 +238,6 @@
 
 /*****************************************************************************/
 
-EXPORT_SYMBOL(ecdev_is_ec);
 EXPORT_SYMBOL(ecdev_receive);
 EXPORT_SYMBOL(ecdev_link_state);
 
--- a/master/master.c	Tue Apr 11 14:39:17 2006 +0000
+++ b/master/master.c	Wed Apr 12 10:40:32 2006 +0000
@@ -25,14 +25,17 @@
 
 /*****************************************************************************/
 
+void ec_master_freerun(unsigned long);
 ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
 
 /*****************************************************************************/
 
 EC_SYSFS_READ_ATTR(slave_count);
+EC_SYSFS_READ_ATTR(mode);
 
 static struct attribute *ec_def_attrs[] = {
     &attr_slave_count,
+    &attr_mode,
     NULL,
 };
 
@@ -78,6 +81,11 @@
         return -1;
     }
 
+    // Init freerun timer
+    init_timer(&master->freerun_timer);
+    master->freerun_timer.function = ec_master_freerun;
+    master->freerun_timer.data = (unsigned long) master;
+
     ec_command_init(&master->simple_command);
     ec_command_init(&master->watch_command);
 
@@ -100,6 +108,8 @@
 
     EC_INFO("Clearing master %i...\n", master->index);
 
+    del_timer_sync(&master->freerun_timer);
+
     ec_master_reset(master);
 
     if (master->device) {
@@ -131,6 +141,8 @@
     ec_domain_t *domain, *next_d;
     ec_eoe_t *eoe, *next_eoe;
 
+    ec_master_freerun_stop(master);
+
     // Alle Slaves entfernen
     list_for_each_entry_safe(slave, next_s, &master->slaves, list) {
         list_del(&slave->list);
@@ -172,6 +184,8 @@
     master->stats.unmatched = 0;
     master->stats.eoe_errors = 0;
     master->stats.t_last = 0;
+
+    master->mode = EC_MASTER_MODE_IDLE;
 }
 
 /*****************************************************************************/
@@ -606,6 +620,61 @@
 /*****************************************************************************/
 
 /**
+   Starts Free-Run mode.
+*/
+
+void ec_master_freerun_start(ec_master_t *master /**< EtherCAT master */)
+{
+    if (master->mode == EC_MASTER_MODE_FREERUN) return;
+
+    if (master->mode == EC_MASTER_MODE_RUNNING) {
+        EC_ERR("ec_master_freerun_start: Master already running!\n");
+        return;
+    }
+
+    EC_INFO("Starting Free-Run mode.\n");
+
+    master->mode = EC_MASTER_MODE_FREERUN;
+
+    master->freerun_timer.expires = jiffies + 10;
+    add_timer(&master->freerun_timer);
+}
+
+/*****************************************************************************/
+
+/**
+   Stops Free-Run mode.
+*/
+
+void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */)
+{
+    if (master->mode != EC_MASTER_MODE_FREERUN) return;
+
+    EC_INFO("Stopping Free-Run mode.\n");
+
+    del_timer_sync(&master->freerun_timer);
+    master->mode = EC_MASTER_MODE_IDLE;
+}
+
+/*****************************************************************************/
+
+/**
+   Free-Run mode function.
+*/
+
+void ec_master_freerun(unsigned long data)
+{
+    ec_master_t *master = (ec_master_t *) data;
+
+    // nop
+
+    master->freerun_timer.expires += HZ;
+    add_timer(&master->freerun_timer);
+}
+
+/*****************************************************************************/
+
+/**
    Wandelt eine ASCII-kodierte Bus-Adresse in einen Slave-Zeiger.
 
    Gültige Adress-Strings sind Folgende:
@@ -795,6 +864,16 @@
     if (attr == &attr_slave_count) {
         return sprintf(buffer, "%i\n", master->slave_count);
     }
+    else if (attr == &attr_mode) {
+        switch (master->mode) {
+            case EC_MASTER_MODE_IDLE:
+                return sprintf(buffer, "IDLE\n");
+            case EC_MASTER_MODE_FREERUN:
+                return sprintf(buffer, "FREERUN\n");
+            case EC_MASTER_MODE_RUNNING:
+                return sprintf(buffer, "RUNNING\n");
+        }
+    }
 
     return 0;
 }
--- a/master/master.h	Tue Apr 11 14:39:17 2006 +0000
+++ b/master/master.h	Wed Apr 12 10:40:32 2006 +0000
@@ -13,6 +13,7 @@
 
 #include <linux/list.h>
 #include <linux/sysfs.h>
+#include <linux/timer.h>
 
 #include "device.h"
 #include "domain.h"
@@ -20,6 +21,20 @@
 /*****************************************************************************/
 
 /**
+   EtherCAT master mode.
+*/
+
+typedef enum
+{
+    EC_MASTER_MODE_IDLE,
+    EC_MASTER_MODE_FREERUN,
+    EC_MASTER_MODE_RUNNING
+}
+ec_master_mode_t;
+
+/*****************************************************************************/
+
+/**
    EtherCAT-Rahmen-Statistiken.
 */
 
@@ -63,6 +78,8 @@
     unsigned int timeout; /**< Timeout für synchronen Datenaustausch */
     struct list_head eoe_slaves; /**< Ethernet over EtherCAT Slaves */
     unsigned int reserved; /**< Master durch Echtzeitprozess reserviert */
+    struct timer_list freerun_timer; /**< Timer fuer Free-Run-Modus. */
+    ec_master_mode_t mode; /**< Modus des Masters */
 };
 
 /*****************************************************************************/
@@ -72,6 +89,10 @@
 void ec_master_clear(struct kobject *);
 void ec_master_reset(ec_master_t *);
 
+// Free-Run
+void ec_master_freerun_start(ec_master_t *);
+void ec_master_freerun_stop(ec_master_t *);
+
 // IO
 void ec_master_receive(ec_master_t *, const uint8_t *, size_t);
 void ec_master_queue_command(ec_master_t *, ec_command_t *);
--- a/master/module.c	Tue Apr 11 14:39:17 2006 +0000
+++ b/master/module.c	Wed Apr 12 10:40:32 2006 +0000
@@ -181,7 +181,7 @@
 
     if (!net_dev) {
         EC_WARN("Device is NULL!\n");
-        return NULL;
+        goto out_return;
     }
 
     if (!(master = ec_find_master(master_index))) return NULL;
@@ -189,23 +189,30 @@
     // critical section start
     if (master->device) {
         EC_ERR("Master %i already has a device!\n", master_index);
-        return NULL;
+        // critical section leave
+        goto out_return;
     }
 
     if (!(master->device =
           (ec_device_t *) kmalloc(sizeof(ec_device_t), GFP_KERNEL))) {
         EC_ERR("Failed to allocate device!\n");
-        return NULL;
+        // critical section leave
+        goto out_return;
     }
     // critical section end
 
     if (ec_device_init(master->device, master, net_dev, isr, module)) {
-        kfree(master->device);
-        master->device = NULL;
-        return NULL;
+        EC_ERR("Failed to init device!\n");
+        goto out_free;
     }
 
     return master->device;
+
+ out_free:
+    kfree(master->device);
+    master->device = NULL;
+ out_return:
+    return NULL;
 }
 
 /*****************************************************************************/
@@ -222,11 +229,6 @@
 {
     ec_master_t *master;
 
-    if (master_index >= ec_master_count) {
-        EC_WARN("Master %i does not exist!\n", master_index);
-        return;
-    }
-
     if (!(master = ec_find_master(master_index))) return;
 
     if (!master->device || master->device != device) {
@@ -239,6 +241,47 @@
     master->device = NULL;
 }
 
+/*****************************************************************************/
+
+/**
+   Starts the master.
+*/
+
+int ecdev_start(unsigned int master_index
+                /**< Index des EtherCAT-Masters */
+                )
+{
+    ec_master_t *master;
+    if (!(master = ec_find_master(master_index))) return -1;
+
+    if (ec_device_open(master->device)) {
+        EC_ERR("Failed to open device!\n");
+        return -1;
+    }
+
+    ec_master_freerun_start(master);
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Stops the master.
+*/
+
+void ecdev_stop(unsigned int master_index
+                /**< Index des EtherCAT-Masters */
+                )
+{
+    ec_master_t *master;
+    if (!(master = ec_find_master(master_index))) return;
+
+    ec_master_freerun_stop(master);
+
+    if (ec_device_close(master->device))
+        EC_WARN("Failed to close device!\n");
+}
+
 /******************************************************************************
  *
  * Echtzeitschnittstelle
@@ -261,50 +304,46 @@
 
     EC_INFO("Requesting master %i...\n", master_index);
 
-    if (!(master = ec_find_master(master_index))) goto req_return;
+    if (!(master = ec_find_master(master_index))) goto out_return;
 
     // begin critical section
     if (master->reserved) {
         EC_ERR("Master %i is already in use!\n", master_index);
-        goto req_return;
+        goto out_return;
     }
     master->reserved = 1;
     // end critical section
 
     if (!master->device) {
         EC_ERR("Master %i has no assigned device!\n", master_index);
-        goto req_release;
+        goto out_release;
     }
 
     if (!try_module_get(master->device->module)) {
         EC_ERR("Failed to reserve device module!\n");
-        goto req_release;
-    }
-
-    if (ec_device_open(master->device)) {
-        EC_ERR("Failed to open device!\n");
-        goto req_module_put;
-    }
+        goto out_release;
+    }
+
+    ec_master_freerun_stop(master);
+    ec_master_reset(master);
+    master->mode = EC_MASTER_MODE_RUNNING;
 
     if (!master->device->link_state) EC_WARN("Link is DOWN.\n");
 
     if (ec_master_bus_scan(master)) {
         EC_ERR("Bus scan failed!\n");
-        goto req_close;
+        goto out_module_put;
     }
 
     EC_INFO("Master %i is ready.\n", master_index);
     return master;
 
- req_close:
-    if (ec_device_close(master->device))
-        EC_WARN("Warning - Failed to close device!\n");
- req_module_put:
+ out_module_put:
     module_put(master->device->module);
     ec_master_reset(master);
- req_release:
+ out_release:
     master->reserved = 0;
- req_return:
+ out_return:
     EC_ERR("Failed requesting master %i.\n", master_index);
     return NULL;
 }
@@ -326,8 +365,8 @@
 
     ec_master_reset(master);
 
-    if (ec_device_close(master->device))
-        EC_WARN("Warning - Failed to close device!\n");
+    master->mode = EC_MASTER_MODE_IDLE;
+    ec_master_freerun_start(master);
 
     module_put(master->device->module);
     master->reserved = 0;
@@ -389,6 +428,8 @@
 
 EXPORT_SYMBOL(ecdev_register);
 EXPORT_SYMBOL(ecdev_unregister);
+EXPORT_SYMBOL(ecdev_start);
+EXPORT_SYMBOL(ecdev_stop);
 EXPORT_SYMBOL(ecrt_request_master);
 EXPORT_SYMBOL(ecrt_release_master);
 
--- a/rt/msr_rt.c	Tue Apr 11 14:39:17 2006 +0000
+++ b/rt/msr_rt.c	Wed Apr 12 10:40:32 2006 +0000
@@ -179,7 +179,7 @@
     }
     ecrt_master_print(master, 2);
 #else
-    ecrt_master_print(master, 1);
+    ecrt_master_print(master, 0);
 #endif
 
 #if 1