Domains, Warten beim Senden, 10kHz.
authorFlorian Pose <fp@igh-essen.com>
Thu, 05 Jan 2006 13:39:39 +0000
changeset 42 a22a202d0f42
parent 41 42c66194c0c8
child 43 35120a61d55e
Domains, Warten beim Senden, 10kHz.
drivers/Makefile
drivers/ec_device.c
drivers/ec_domain.c
drivers/ec_domain.h
drivers/ec_globals.h
drivers/ec_master.c
drivers/ec_master.h
drivers/ec_module.c
drivers/ec_slave.c
drivers/ec_slave.h
drivers/ec_types.h
mini/ec_mini.c
rt/msr_jitter.c
rt/msr_module.c
rt/msr_param.h
--- a/drivers/Makefile	Fri Dec 23 08:23:35 2005 +0000
+++ b/drivers/Makefile	Thu Jan 05 13:39:39 2006 +0000
@@ -18,7 +18,7 @@
 8139too-ecat-objs := 8139too.o
 
 ecat-master-objs := ec_module.o ec_master.o ec_device.o ec_slave.o \
-					ec_command.o ec_types.o
+			ec_command.o ec_types.o ec_domain.o
 
 REV = `svnversion $(src)`
 DATE = `date`
--- a/drivers/ec_device.c	Fri Dec 23 08:23:35 2005 +0000
+++ b/drivers/ec_device.c	Thu Jan 05 13:39:39 2006 +0000
@@ -131,6 +131,8 @@
 
 int EtherCAT_device_open(EtherCAT_device_t *ecd)
 {
+  unsigned int i;
+
   if (!ecd) {
     printk(KERN_ERR "EtherCAT: Trying to open a NULL device!\n");
     return -1;
@@ -141,6 +143,9 @@
     return -1;
   }
 
+  // Device could have received frames before
+  for (i = 0; i < 4; i++) EtherCAT_device_call_isr(ecd);
+
   // Reset old device state
   ecd->state = ECAT_DS_READY;
   ecd->tx_intr_cnt = 0;
@@ -265,7 +270,7 @@
   if (unlikely(ecd->rx_data_length > ECAT_FRAME_BUFFER_SIZE)) {
     if (likely(ecd->error_reported)) {
       printk(KERN_ERR "EtherCAT: receive - "
-             " Reveived frame too long (%i Bytes)!\n",
+             " Reveived frame is too long (%i Bytes)!\n",
              ecd->rx_data_length);
       ecd->error_reported = 1;
     }
@@ -284,7 +289,7 @@
 /*****************************************************************************/
 
 /**
-   Ruft manuell die Interrupt-Routine der Netzwerkkarte auf.
+   Ruft die Interrupt-Routine der Netzwerkkarte auf.
 
    @param ecd EtherCAT-Gerät
 
@@ -350,3 +355,9 @@
 EXPORT_SYMBOL(EtherCAT_device_close);
 
 /*****************************************************************************/
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:2 ***
+;;; End: ***
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/ec_domain.c	Thu Jan 05 13:39:39 2006 +0000
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ *  e c _ d o m a i n . c
+ *
+ *  Methoden für Gruppen von EtherCAT-Slaves.
+ *
+ *  $Id$
+ *
+ *****************************************************************************/
+
+#include <linux/module.h>
+
+#include "ec_globals.h"
+#include "ec_domain.h"
+
+/*****************************************************************************/
+
+/**
+   Konstruktor einer EtherCAT-Domäne.
+
+   @param pd Zeiger auf die zu initialisierende Domäne
+*/
+
+void EtherCAT_domain_init(EtherCAT_domain_t *dom)
+{
+  dom->number = 0;
+  dom->data = NULL;
+  dom->data_size = 0;
+  dom->logical_offset = 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Destruktor eines Prozessdatenobjekts.
+
+   @param dom Zeiger auf die zu löschenden Prozessdaten
+*/
+
+void EtherCAT_domain_clear(EtherCAT_domain_t *dom)
+{
+  if (dom->data) {
+    kfree(dom->data);
+    dom->data = NULL;
+  }
+
+  dom->data_size = 0;
+}
+
+/*****************************************************************************/
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:2 ***
+;;; End: ***
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/ec_domain.h	Thu Jan 05 13:39:39 2006 +0000
@@ -0,0 +1,51 @@
+/******************************************************************************
+ *
+ *  e c _ d o m a i n . h
+ *
+ *  Struktur für eine Gruppe von EtherCAT-Slaves.
+ *
+ *  $Id$
+ *
+ *****************************************************************************/
+
+#ifndef _EC_DOMAIN_H_
+#define _EC_DOMAIN_H_
+
+#include "ec_globals.h"
+#include "ec_slave.h"
+#include "ec_command.h"
+
+/*****************************************************************************/
+
+/**
+   EtherCAT-Domäne
+
+   Verwaltet die Prozessdaten und das hierfür nötige Kommando einer bestimmten
+   Menge von Slaves.
+*/
+
+typedef struct EtherCAT_domain
+{
+  unsigned int number; /*<< Domänen-Identifikation */
+  EtherCAT_command_t command; /**< Kommando zum Senden und Empfangen der
+                                 Prozessdaten */
+  unsigned char *data; /**< Zeiger auf Speicher mit Prozessdaten */
+  unsigned int data_size; /**< Größe des Prozessdatenspeichers */
+  unsigned int logical_offset; /**< Logische Basisaddresse */
+}
+EtherCAT_domain_t;
+
+/*****************************************************************************/
+
+void EtherCAT_domain_init(EtherCAT_domain_t *);
+void EtherCAT_domain_clear(EtherCAT_domain_t *);
+
+/*****************************************************************************/
+
+#endif
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:2 ***
+;;; End: ***
+*/
--- a/drivers/ec_globals.h	Fri Dec 23 08:23:35 2005 +0000
+++ b/drivers/ec_globals.h	Thu Jan 05 13:39:39 2006 +0000
@@ -19,6 +19,11 @@
 #define ECAT_FRAME_BUFFER_SIZE 1500
 
 /**
+   Maximale Anzahl der Prozessdatendomänen in einem Master
+*/
+#define ECAT_MAX_DOMAINS 10
+
+/**
    NULL-Define, falls noch nicht definiert.
 */
 
@@ -69,4 +74,8 @@
 
 /*****************************************************************************/
 
+typedef struct EtherCAT_master EtherCAT_master_t;
+
+/*****************************************************************************/
+
 #endif
--- a/drivers/ec_master.c	Fri Dec 23 08:23:35 2005 +0000
+++ b/drivers/ec_master.c	Thu Jan 05 13:39:39 2006 +0000
@@ -22,22 +22,20 @@
 /**
    Konstruktor des EtherCAT-Masters.
 
-   @param master Zeiger auf den zu initialisierenden
-   EtherCAT-Master
-
-   @return 0 bei Erfolg, sonst < 0 (= dev ist NULL)
+   @param master Zeiger auf den zu initialisierenden EtherCAT-Master
 */
 
 void EtherCAT_master_init(EtherCAT_master_t *master)
 {
-  master->slaves = NULL;
-  master->slave_count = 0;
   master->dev = NULL;
   master->command_index = 0x00;
   master->tx_data_length = 0;
-  master->process_data = NULL;
-  master->process_data_length = 0;
+  master->rx_data_length = 0;
+  master->domain_count = 0;
   master->debug_level = 0;
+  master->tx_time = 0;
+  master->rx_time = 0;
+  master->rx_tries = 0;
 }
 
 /*****************************************************************************/
@@ -53,15 +51,14 @@
 
 void EtherCAT_master_clear(EtherCAT_master_t *master)
 {
-  // Remove all slaves
-  EtherCAT_clear_slaves(master);
-
-  if (master->process_data) {
-    kfree(master->process_data);
-    master->process_data = NULL;
-  }
-
-  master->process_data_length = 0;
+  unsigned int i;
+
+  // Remove domains
+  for (i = 0; i < master->domain_count; i++) {
+    EtherCAT_domain_clear(master->domains + i);
+  }
+
+  master->domain_count = 0;
 }
 
 /*****************************************************************************/
@@ -82,14 +79,12 @@
                          EtherCAT_device_t *device)
 {
   if (!master || !device) {
-    printk(KERN_ERR "EtherCAT: Illegal parameters"
-           " for master_open()!\n");
+    printk(KERN_ERR "EtherCAT: Illegal parameters for master_open()!\n");
     return -1;
   }
 
   if (master->dev) {
-    printk(KERN_ERR "EtherCAT: Master already"
-           " has a device.\n");
+    printk(KERN_ERR "EtherCAT: Master already has a device.\n");
     return -1;
   }
 
@@ -197,8 +192,7 @@
   framelength = length + 2;
 
   if (unlikely(framelength > ECAT_FRAME_BUFFER_SIZE)) {
-    printk(KERN_ERR "EtherCAT: Frame too long (%i)!\n",
-           framelength);
+    printk(KERN_ERR "EtherCAT: Frame too long (%i)!\n", framelength);
     return -1;
   }
 
@@ -256,6 +250,9 @@
     printk(KERN_DEBUG "device send...\n");
   }
 
+  // Zeit nehmen
+  rdtscl(master->tx_time);
+
   // Send frame
   if (unlikely(EtherCAT_device_send(master->dev,
                                     master->tx_data,
@@ -297,8 +294,8 @@
   master->rx_data_length = (unsigned int) ret;
 
   if (unlikely(master->rx_data_length < 2)) {
-    printk(KERN_ERR "EtherCAT: Received frame with"
-           " incomplete EtherCAT header!\n");
+    printk(KERN_ERR "EtherCAT: Received frame with incomplete"
+           " EtherCAT header!\n");
     output_debug_data(master);
     return -1;
   }
@@ -308,8 +305,8 @@
     | (master->rx_data[0] & 0xFF);
 
   if (unlikely(length > master->rx_data_length)) {
-    printk(KERN_ERR "EtherCAT: Received corrupted"
-           " frame (length does not match)!\n");
+    printk(KERN_ERR "EtherCAT: Received corrupted frame (length does"
+           " not match)!\n");
     output_debug_data(master);
     return -1;
   }
@@ -337,8 +334,9 @@
     memcpy(cmd->data, master->rx_data + 2 + 10, length);
 
     // Working-Counter setzen
-    cmd->working_counter = ((master->rx_data[length + 2 + 10] & 0xFF)
-                            | ((master->rx_data[length + 2 + 11] & 0xFF) << 8));
+    cmd->working_counter
+      = ((master->rx_data[length + 2 + 10] & 0xFF)
+         | ((master->rx_data[length + 2 + 11] & 0xFF) << 8));
   }
   else
   {
@@ -374,8 +372,17 @@
 {
   EtherCAT_command_t cmd;
   EtherCAT_slave_t *cur;
-  unsigned int i, j, found, length, pos;
+  unsigned int i, j, found, size, offset;
   unsigned char data[2];
+  EtherCAT_domain_t *dom;
+
+  // Clear domains
+  for (i = 0; i < master->domain_count; i++) {
+    printk(KERN_DEBUG "EtherCAT: Clearing domain %i!\n",
+           master->domains[i].number);
+    EtherCAT_domain_clear(master->domains + i);
+  }
+  master->domain_count = 0;
 
   if (unlikely(!slave_count)) {
     printk(KERN_ERR "EtherCAT: No slaves in list!\n");
@@ -394,8 +401,8 @@
            cmd.working_counter, slave_count);
     return -1;
   }
-  else
-    printk("EtherCAT: Found all %i slaves.\n", slave_count);
+
+  printk("EtherCAT: Found all %i slaves.\n", slave_count);
 
   // For every slave in the list
   for (i = 0; i < slave_count; i++)
@@ -403,8 +410,7 @@
     cur = &slaves[i];
 
     if (unlikely(!cur->desc)) {
-      printk(KERN_ERR "EtherCAT: Slave %i has"
-             " no description.\n", i);
+      printk(KERN_ERR "EtherCAT: Slave %i has no description.\n", i);
       return -1;
     }
 
@@ -443,6 +449,7 @@
     }
 
     // Get base data
+
     cur->type = cmd.data[0];
     cur->revision = cmd.data[1];
     cur->build = cmd.data[2] | (cmd.data[3] << 8);
@@ -515,42 +522,75 @@
              cur->vendor_id, cur->product_code, i);
       return -1;
     }
-  }
-
-  length = 0;
-  for (i = 0; i < slave_count; i++)
-  {
-    length += slaves[i].desc->data_length;
-  }
-
-  if (unlikely((master->process_data = (unsigned char *)
-                kmalloc(sizeof(unsigned char)
-                        * length, GFP_KERNEL)) == NULL)) {
-    printk(KERN_ERR "EtherCAT: Could not allocate %i"
-           " bytes for process data.\n", length);
-    return -1;
-  }
-
-  master->process_data_length = length;
-  memset(master->process_data, 0x00, length);
-
-  pos = 0;
-  for (i = 0; i < slave_count; i++)
-  {
-    slaves[i].process_data = master->process_data + pos;
-    slaves[i].logical_address0 = pos;
-
-    printk(KERN_DEBUG "EtherCAT: Slave %i -"
-           " Address 0x%X, \"%s %s\", s/n %u\n",
-           i, pos, slaves[i].desc->vendor_name,
-           slaves[i].desc->product_name,
-           slaves[i].serial_number);
-
-    pos += slaves[i].desc->data_length;
-  }
-
-  master->slaves = slaves;
-  master->slave_count = slave_count;
+
+    // Check, if process data domain already exists...
+    found = 0;
+    for (j = 0; j < master->domain_count; j++) {
+      if (cur->domain == master->domains[j].number) {
+        found = 1;
+      }
+    }
+
+    // Create process data domain
+    if (!found) {
+      if (master->domain_count + 1 >= ECAT_MAX_DOMAINS) {
+        printk(KERN_ERR "EtherCAT: Too many domains!\n");
+        return -1;
+      }
+
+      EtherCAT_domain_init(&master->domains[master->domain_count]);
+      master->domains[master->domain_count].number = cur->domain;
+      master->domain_count++;
+    }
+  }
+
+  // Calculate domain sizes
+  offset = 0;
+  for (i = 0; i < master->domain_count; i++)
+  {
+    dom = master->domains + i;
+
+    dom->logical_offset = offset;
+
+    // For every slave in the list
+    size = 0;
+    for (j = 0; j < slave_count; j++) {
+      if (slaves[j].domain == dom->number) {
+        size += slaves[j].desc->process_data_size;
+      }
+    }
+
+    if (size > ECAT_FRAME_BUFFER_SIZE - 14) {
+      printk(KERN_ERR "EtherCAT: Oversized domain %i: %i / %i Bytes!\n",
+             dom->number, size, ECAT_FRAME_BUFFER_SIZE - 14);
+      return -1;
+    }
+
+    if (!(dom->data = (unsigned char *) kmalloc(sizeof(unsigned char)
+                                               * size, GFP_KERNEL))) {
+      printk(KERN_ERR "EtherCAT: Could not allocate"
+             " %i bytes of domain data.\n", size);
+      return -1;
+    }
+
+    dom->data_size = size;
+    memset(dom->data, 0x00, size);
+
+    printk(KERN_INFO "EtherCAT: Domain %i: %i Bytes of process data.\n",
+           dom->number, size);
+
+    // Set logical addresses and data pointers of domain slaves
+    size = 0;
+    for (j = 0; j < slave_count; j++) {
+      if (slaves[j].domain == dom->number) {
+        slaves[j].process_data = dom->data + size;
+        slaves[j].logical_address = dom->logical_offset + size;
+        size += slaves[j].desc->process_data_size;
+      }
+    }
+
+    offset += size;
+  }
 
   return 0;
 }
@@ -558,20 +598,6 @@
 /*****************************************************************************/
 
 /**
-   Entfernt den Zeiger auf das Slave-Array.
-
-   @param master EtherCAT-Master
-*/
-
-void EtherCAT_clear_slaves(EtherCAT_master_t *master)
-{
-  master->slaves = NULL;
-  master->slave_count = 0;
-}
-
-/*****************************************************************************/
-
-/**
    Liest Daten aus dem Slave-Information-Interface
    eines EtherCAT-Slaves.
 
@@ -605,12 +631,12 @@
   EtherCAT_command_write(&cmd, node_address, 0x502, 6, data);
 
   if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
-    return -3;
+    return -1;
 
   if (unlikely(cmd.working_counter != 1)) {
-    printk(KERN_ERR "EtherCAT: SII-read - Slave"
-           " %04X did not respond!\n", node_address);
-    return -4;
+    printk(KERN_ERR "EtherCAT: SII-read - Slave %04X did not respond!\n",
+           node_address);
+    return -1;
   }
 
   // Der Slave legt die Informationen des Slave-Information-Interface
@@ -625,12 +651,12 @@
     EtherCAT_command_read(&cmd, node_address, 0x502, 10);
 
     if (unlikely(EtherCAT_simple_send_receive(master, &cmd) != 0))
-      return -3;
+      return -1;
 
     if (unlikely(cmd.working_counter != 1)) {
       printk(KERN_ERR "EtherCAT: SII-read status -"
              " Slave %04X did not respond!\n", node_address);
-      return -4;
+      return -1;
     }
 
     if (likely((cmd.data[1] & 0x81) == 0)) {
@@ -642,8 +668,8 @@
   }
 
   if (unlikely(!tries_left)) {
-    printk(KERN_WARNING "EtherCAT: SSI-read."
-           " Slave %04X timed out!\n", node_address);
+    printk(KERN_WARNING "EtherCAT: SSI-read. Slave %04X timed out!\n",
+           node_address);
     return -1;
   }
 
@@ -784,7 +810,7 @@
     printk(KERN_ERR "EtherCAT: Resetting FMMUs -"
            " Slave %04X did not respond!\n",
            slave->station_address);
-    return -2;
+    return -1;
   }
 
   // Resetting Sync Manager channels
@@ -803,7 +829,7 @@
       printk(KERN_ERR "EtherCAT: Resetting SMs -"
              " Slave %04X did not respond!\n",
              slave->station_address);
-      return -2;
+      return -1;
     }
   }
 
@@ -823,7 +849,7 @@
         printk(KERN_ERR "EtherCAT: Setting SM0 -"
                " Slave %04X did not respond!\n",
                slave->station_address);
-        return -3;
+        return -1;
       }
     }
 
@@ -839,7 +865,7 @@
         printk(KERN_ERR "EtherCAT: Setting SM1 -"
                " Slave %04X did not respond!\n",
                slave->station_address);
-        return -2;
+        return -1;
       }
     }
   }
@@ -848,18 +874,24 @@
 
   if (unlikely(EtherCAT_state_change(master, slave,
                                      ECAT_STATE_PREOP) != 0))
-    return -5;
+    return -1;
 
   // Set FMMU's
 
   if (desc->fmmu0)
   {
+    if (unlikely(!slave->process_data)) {
+      printk(KERN_ERR "EtherCAT: Warning - Slave %04X is not assigned to any"
+             " process data object!\n", slave->station_address);
+      return -1;
+    }
+
     memcpy(fmmu, desc->fmmu0, 16);
 
-    fmmu[0] = slave->logical_address0 & 0x000000FF;
-    fmmu[1] = (slave->logical_address0 & 0x0000FF00) >> 8;
-    fmmu[2] = (slave->logical_address0 & 0x00FF0000) >> 16;
-    fmmu[3] = (slave->logical_address0 & 0xFF000000) >> 24;
+    fmmu[0] = slave->logical_address & 0x000000FF;
+    fmmu[1] = (slave->logical_address & 0x0000FF00) >> 8;
+    fmmu[2] = (slave->logical_address & 0x00FF0000) >> 16;
+    fmmu[3] = (slave->logical_address & 0xFF000000) >> 24;
 
     EtherCAT_command_write(&cmd, slave->station_address,
                            0x0600, 16, fmmu);
@@ -871,7 +903,7 @@
       printk(KERN_ERR "EtherCAT: Setting FMMU0 -"
              " Slave %04X did not respond!\n",
              slave->station_address);
-      return -2;
+      return -1;
     }
   }
 
@@ -891,7 +923,7 @@
         printk(KERN_ERR "EtherCAT: Setting SM0 -"
                " Slave %04X did not respond!\n",
                slave->station_address);
-        return -3;
+        return -1;
       }
     }
 
@@ -907,7 +939,7 @@
         printk(KERN_ERR "EtherCAT: Setting SM1 -"
                " Slave %04X did not respond!\n",
                slave->station_address);
-        return -3;
+        return -1;
       }
     }
   }
@@ -924,7 +956,7 @@
       printk(KERN_ERR "EtherCAT: Setting SM2 -"
              " Slave %04X did not respond!\n",
              slave->station_address);
-      return -3;
+      return -1;
     }
   }
 
@@ -940,19 +972,19 @@
       printk(KERN_ERR "EtherCAT: Setting SM3 -"
              " Slave %04X did not respond!\n",
              slave->station_address);
-      return -3;
+      return -1;
     }
   }
 
   // Change state to SAVEOP
   if (unlikely(EtherCAT_state_change(master, slave,
                                      ECAT_STATE_SAVEOP) != 0))
-    return -12;
+    return -1;
 
   // Change state to OP
   if (unlikely(EtherCAT_state_change(master, slave,
                                      ECAT_STATE_OP) != 0))
-    return -13;
+    return -1;
 
   return 0;
 }
@@ -981,137 +1013,74 @@
 /*****************************************************************************/
 
 /**
-   Aktiviert alle Slaves.
-
-   @see EtherCAT_activate_slave
+   Sendet und empfängt Prozessdaten der angegebenen Domäne
 
    @param master EtherCAT-Master
+          domain Domäne
 
    @return 0 bei Erfolg, sonst < 0
 */
 
-int EtherCAT_activate_all_slaves(EtherCAT_master_t *master)
-{
-  unsigned int i;
-
-  for (i = 0; i < master->slave_count; i++)
-  {
-    if (unlikely(EtherCAT_activate_slave(master,
-                                         &master->slaves[i]) < 0))
-      return -1;
-  }
-
-  return 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Deaktiviert alle Slaves.
-
-   @see EtherCAT_deactivate_slave
-
-   @param master EtherCAT-Master
-
-   @return 0 bei Erfolg, sonst < 0
-*/
-
-int EtherCAT_deactivate_all_slaves(EtherCAT_master_t *master)
-{
-  unsigned int i;
-  int ret = 0;
-
-  for (i = 0; i < master->slave_count; i++)
-  {
-    if (unlikely(EtherCAT_deactivate_slave(master,
-                                           &master->slaves[i]) < 0))
-      ret = -1;
-  }
-
-  return ret;
-}
-
-/*****************************************************************************/
-
-/**
-   Sendet alle Prozessdaten an die Slaves.
-
-   Erstellt ein "logical read write"-Kommando mit den
-   Prozessdaten des Masters und sendet es an den Bus.
-
-   @param master EtherCAT-Master
-
-   @return 0 bei Erfolg, sonst < 0
-*/
-
-int EtherCAT_write_process_data(EtherCAT_master_t *master)
-{
-  EtherCAT_command_logical_read_write(&master->process_data_command,
-                                      0, master->process_data_length,
-                                      master->process_data);
-
-  if (unlikely(EtherCAT_simple_send(master,
-                                    &master->process_data_command) < 0))
-  {
-    printk(KERN_ERR "EtherCAT: Could not send"
-           " process data command!\n");
-    return -1;
-  }
-
-  return 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Empfängt alle Prozessdaten von den Slaves.
-
-   Empfängt ein zuvor gesendetes "logical read write"-Kommando
-   und kopiert die empfangenen daten in den Prozessdatenspeicher
-   des Masters.
-
-   @param master EtherCAT-Master
-
-   @return 0 bei Erfolg, sonst < 0
-*/
-
-int EtherCAT_read_process_data(EtherCAT_master_t *master)
-{
-  unsigned int tries_left;
-
+int EtherCAT_process_data_cycle(EtherCAT_master_t *master,
+                                unsigned int domain)
+{
+  unsigned int i, tries;
+  EtherCAT_domain_t *dom = NULL;
+
+  for (i = 0; i < master->domain_count; i++) {
+    if (master->domains[i].number == domain) {
+      dom = master->domains + i;
+      break;
+    }
+  }
+
+  if (unlikely(!dom)) {
+    printk(KERN_ERR "EtherCAT: No such domain: %i!\n", domain);
+    return -1;
+  }
+
+  EtherCAT_command_logical_read_write(&dom->command,
+                                      dom->logical_offset, dom->data_size,
+                                      dom->data);
+
+  if (unlikely(EtherCAT_simple_send(master, &dom->command) < 0)) {
+    printk(KERN_ERR "EtherCAT: Could not send process data command!\n");
+    return -1;
+  }
+
+  udelay(3);
+
+#if 1
+  // Warten
+  tries = 0;
   EtherCAT_device_call_isr(master->dev);
-
-  tries_left = 20;
-  while (unlikely(master->dev->state == ECAT_DS_SENT
-                  && tries_left))
-  {
+  while (unlikely(master->dev->state == ECAT_DS_SENT && tries < 100)) {
     udelay(1);
     EtherCAT_device_call_isr(master->dev);
-    tries_left--;
-  }
-
-  if (unlikely(!tries_left))
-  {
+    tries++;
+  }
+
+  rdtscl(master->rx_time);
+  master->rx_tries = tries;
+
+  if (unlikely(tries == 100)) {
     printk(KERN_ERR "EtherCAT: Timeout while receiving process data!\n");
     return -1;
   }
 
-  if (unlikely(EtherCAT_simple_receive(master,
-                                       &master->process_data_command) < 0))
-  {
+  if (unlikely(EtherCAT_simple_receive(master, &dom->command) < 0)) {
     printk(KERN_ERR "EtherCAT: Could not receive cyclic command!\n");
     return -1;
   }
 
-  if (unlikely(master->process_data_command.state != ECAT_CS_RECEIVED))
-  {
+  if (unlikely(dom->command.state != ECAT_CS_RECEIVED)) {
     printk(KERN_WARNING "EtherCAT: Process data command not received!\n");
     return -1;
   }
 
-  // Daten von Kommando in Prozessdaten des Master kopieren
-  memcpy(master->process_data, master->process_data_command.data,
-         master->process_data_length);
+  // Daten vom Kommando in den Prozessdatenspeicher kopieren
+  memcpy(dom->data, dom->command.data, dom->data_size);
+#endif
 
   return 0;
 }
@@ -1119,20 +1088,6 @@
 /*****************************************************************************/
 
 /**
-   Verwirft das zuletzt gesendete Prozessdatenkommando.
-
-   @param master EtherCAT-Master
-*/
-
-void EtherCAT_clear_process_data(EtherCAT_master_t *master)
-{
-  EtherCAT_device_call_isr(master->dev);
-  master->dev->state = ECAT_DS_READY;
-}
-
-/*****************************************************************************/
-
-/**
    Gibt Frame-Inhalte zwecks Debugging aus.
 
    @param master EtherCAT-Master
@@ -1171,11 +1126,15 @@
 EXPORT_SYMBOL(EtherCAT_master_clear);
 EXPORT_SYMBOL(EtherCAT_master_open);
 EXPORT_SYMBOL(EtherCAT_master_close);
-EXPORT_SYMBOL(EtherCAT_read_process_data);
-EXPORT_SYMBOL(EtherCAT_write_process_data);
 EXPORT_SYMBOL(EtherCAT_check_slaves);
-EXPORT_SYMBOL(EtherCAT_activate_all_slaves);
-EXPORT_SYMBOL(EtherCAT_clear_process_data);
-EXPORT_SYMBOL(EtherCAT_deactivate_all_slaves);
-
-/*****************************************************************************/
+EXPORT_SYMBOL(EtherCAT_activate_slave);
+EXPORT_SYMBOL(EtherCAT_deactivate_slave);
+EXPORT_SYMBOL(EtherCAT_process_data_cycle);
+
+/*****************************************************************************/
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:2 ***
+;;; End: ***
+*/
--- a/drivers/ec_master.h	Fri Dec 23 08:23:35 2005 +0000
+++ b/drivers/ec_master.h	Thu Jan 05 13:39:39 2006 +0000
@@ -14,6 +14,7 @@
 #include "ec_device.h"
 #include "ec_slave.h"
 #include "ec_command.h"
+#include "ec_domain.h"
 
 /*****************************************************************************/
 
@@ -24,19 +25,10 @@
    dem zugewiesenen EtherCAT-Gerät.
 */
 
-typedef struct
+struct EtherCAT_master
 {
-  EtherCAT_slave_t *slaves; /**< Zeiger auf statischen Speicher
-                               mit Slave-Informationen */
-  unsigned int slave_count; /**< Anzahl der Slaves in slaves */
-
-  EtherCAT_command_t process_data_command; /**< Kommando zum Senden und
-                                              Empfangen der Prozessdaten */
-
   EtherCAT_device_t *dev; /**< Zeiger auf das zugewiesene EtherCAT-Gerät */
-
   unsigned char command_index; /**< Aktueller Kommando-Index */
-
   unsigned char tx_data[ECAT_FRAME_BUFFER_SIZE]; /**< Statischer Speicher
                                                     für zu sendende Daten */
   unsigned int tx_data_length; /**< Länge der Daten im Sendespeicher */
@@ -44,13 +36,13 @@
                                                     eine Kopie des Rx-Buffers
                                                     im EtherCAT-Gerät */
   unsigned int rx_data_length; /**< Länge der Daten im Empfangsspeicher */
-
-  unsigned char *process_data; /**< Zeiger auf Speicher mit Prozessdaten */
-  unsigned int process_data_length; /**< Länge der Prozessdaten */
-
+  EtherCAT_domain_t domains[ECAT_MAX_DOMAINS]; /** Prozessdatendomänen */
+  unsigned int domain_count;
   int debug_level; /**< Debug-Level im Master-Code */
-}
-EtherCAT_master_t;
+  unsigned long tx_time; /**< Zeit des letzten Sendens */
+  unsigned long rx_time; /**< Zeit des letzten Empfangs */
+  unsigned int rx_tries; /**< Anzahl Warteschleifen beim letzen Enpfang */
+};
 
 /*****************************************************************************/
 
@@ -68,22 +60,17 @@
 int EtherCAT_simple_receive(EtherCAT_master_t *, EtherCAT_command_t *);
 
 // Slave management
-int EtherCAT_check_slaves(EtherCAT_master_t *, EtherCAT_slave_t *, unsigned int);
-void EtherCAT_clear_slaves(EtherCAT_master_t *);
-int EtherCAT_read_slave_information(EtherCAT_master_t *,
-                                    unsigned short int,
-                                    unsigned short int,
-                                    unsigned int *);
+int EtherCAT_check_slaves(EtherCAT_master_t *, EtherCAT_slave_t *,
+                          unsigned int);
+int EtherCAT_read_slave_information(EtherCAT_master_t *, unsigned short int,
+                                    unsigned short int, unsigned int *);
 int EtherCAT_activate_slave(EtherCAT_master_t *, EtherCAT_slave_t *);
 int EtherCAT_deactivate_slave(EtherCAT_master_t *, EtherCAT_slave_t *);
-int EtherCAT_activate_all_slaves(EtherCAT_master_t *);
-int EtherCAT_deactivate_all_slaves(EtherCAT_master_t *);
-int EtherCAT_state_change(EtherCAT_master_t *, EtherCAT_slave_t *, unsigned char);
+int EtherCAT_state_change(EtherCAT_master_t *, EtherCAT_slave_t *,
+                          unsigned char);
 
 // Process data
-int EtherCAT_write_process_data(EtherCAT_master_t *);
-int EtherCAT_read_process_data(EtherCAT_master_t *);
-void EtherCAT_clear_process_data(EtherCAT_master_t *);
+int EtherCAT_process_data_cycle(EtherCAT_master_t *, unsigned int);
 
 // Private functions
 void output_debug_data(const EtherCAT_master_t *);
@@ -91,3 +78,9 @@
 /*****************************************************************************/
 
 #endif
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:2 ***
+;;; End: ***
+*/
--- a/drivers/ec_module.c	Fri Dec 23 08:23:35 2005 +0000
+++ b/drivers/ec_module.c	Thu Jan 05 13:39:39 2006 +0000
@@ -239,7 +239,7 @@
 /*****************************************************************************/
 
 /**
-   Gibt einen zuvor reservierten EtherCAT-Master wieder frei.
+   Gibt einen zuvor angeforderten EtherCAT-Master wieder frei.
 
    @param master Zeiger auf den freizugebenden EtherCAT-Master.
 */
@@ -267,7 +267,7 @@
     }
   }
 
-  printk(KERN_WARNING "EtherCAT: Master %X was never reserved!\n",
+  printk(KERN_WARNING "EtherCAT: Master %X was never requested!\n",
          (unsigned int) master);
 }
 
--- a/drivers/ec_slave.c	Fri Dec 23 08:23:35 2005 +0000
+++ b/drivers/ec_slave.c	Thu Jan 05 13:39:39 2006 +0000
@@ -20,6 +20,9 @@
 
    Initialisiert einen EtherCAT-Slave.
 
+   ACHTUNG! Dieser Konstruktor wird quasi nie aufgerufen. Bitte immer das
+   Makro ECAT_INIT_SLAVE() in ec_slave.h anpassen!
+
    @param slave Zeiger auf den zu initialisierenden Slave
 */
 
@@ -35,9 +38,11 @@
   slave->revision_number = 0;
   slave->serial_number = 0;
   slave->desc = NULL;
-  slave->logical_address0 = 0;
+  slave->logical_address = 0;
   slave->current_state = ECAT_STATE_UNKNOWN;
   slave->requested_state = ECAT_STATE_UNKNOWN;
+  slave->process_data = NULL;
+  slave->domain = 0;
   slave->error_reported = 0;
 }
 
@@ -97,7 +102,7 @@
     return 0;
   }
 
-  if (unlikely(channel >= slave->desc->channels)) {
+  if (unlikely(channel >= slave->desc->channel_count)) {
     if (likely(slave->error_reported)) {
       printk(KERN_WARNING "EtherCAT: Reading failed on slave %4X (addr %0X)"
              " - Type (%s %s) has no channel %i.\n",
@@ -109,6 +114,16 @@
     return 0;
   }
 
+  if (unlikely(!slave->process_data)) {
+    if (likely(slave->error_reported)) {
+      printk(KERN_WARNING "EtherCAT: Reading failed on slave %4X (addr %0X)"
+             " - Slave does not belong to any process data object!\n",
+             slave->station_address, (unsigned int) slave);
+      slave->error_reported = 1;
+    }
+    return 0;
+  }
+
   if (unlikely(slave->error_reported))
     slave->error_reported = 0;
 
@@ -156,7 +171,7 @@
     return;
   }
 
-  if (unlikely(channel >= slave->desc->channels)) {
+  if (unlikely(channel >= slave->desc->channel_count)) {
     if (likely(slave->error_reported)) {
       printk(KERN_WARNING "EtherCAT: Writing failed on slave %4X (addr %0X)"
              " - Type (%s %s) has no channel %i.\n",
@@ -168,6 +183,16 @@
     return;
   }
 
+  if (unlikely(!slave->process_data)) {
+    if (likely(slave->error_reported)) {
+      printk(KERN_WARNING "EtherCAT: Writing failed on slave %4X (addr %0X)"
+             " - Slave does not belong to any process data object!\n",
+             slave->station_address, (unsigned int) slave);
+      slave->error_reported = 1;
+    }
+    return;
+  }
+
   if (unlikely(slave->error_reported))
     slave->error_reported = 0;
 
@@ -180,3 +205,9 @@
 EXPORT_SYMBOL(EtherCAT_read_value);
 
 /*****************************************************************************/
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:2 ***
+;;; End: ***
+*/
--- a/drivers/ec_slave.h	Fri Dec 23 08:23:35 2005 +0000
+++ b/drivers/ec_slave.h	Thu Jan 05 13:39:39 2006 +0000
@@ -42,20 +42,21 @@
   const EtherCAT_slave_desc_t *desc; /**< Zeiger auf die Beschreibung
                                         des Slave-Typs */
 
-  unsigned int logical_address0; /**< Konfigurierte, logische adresse */
+  unsigned int logical_address; /**< Konfigurierte, logische adresse */
 
   EtherCAT_state_t current_state; /**< Aktueller Zustand */
   EtherCAT_state_t requested_state; /**< Angeforderter Zustand */
 
   unsigned char *process_data; /**< Zeiger auf den Speicherbereich
-                                  im Prozessdatenspeicher des Masters */
-  int error_reported; /**< Ein Zugriffsfehler wurde bereits gemeldet. */
+                                  innerhalb eines Prozessdatenobjekts */
+  unsigned int domain; /**< Prozessdatendomäne */
+  int error_reported; /**< Ein Zugriffsfehler wurde bereits gemeldet */
 }
 EtherCAT_slave_t;
 
-#define ECAT_INIT_SLAVE(TYPE) {0, 0, 0, 0, 0, 0, 0, 0, 0, \
-                               TYPE, 0, ECAT_STATE_UNKNOWN, \
-                               ECAT_STATE_UNKNOWN, NULL}
+#define ECAT_INIT_SLAVE(TYPE, DOMAIN) {0, 0, 0, 0, 0, 0, 0, 0, 0, \
+                                       TYPE, 0, ECAT_STATE_UNKNOWN, \
+                                       ECAT_STATE_UNKNOWN, NULL, DOMAIN, 0}
 
 /*****************************************************************************/
 
@@ -69,3 +70,9 @@
 /*****************************************************************************/
 
 #endif
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:2 ***
+;;; End: ***
+*/
--- a/drivers/ec_types.h	Fri Dec 23 08:23:35 2005 +0000
+++ b/drivers/ec_types.h	Thu Jan 05 13:39:39 2006 +0000
@@ -57,8 +57,8 @@
   const unsigned char *fmmu0; /**< Konfigurationsdaten
                                  der ersten FMMU */
 
-  const unsigned int data_length; /**< Länge der Prozessdaten in Bytes */
-  const unsigned int channels; /**< Anzahl der Kanäle */
+  const unsigned int process_data_size; /**< Länge der Prozessdaten in Bytes */
+  const unsigned int channel_count; /**< Anzahl der Kanäle */
 
   int (*read) (unsigned char *, unsigned int); /**< Funktion zum Dekodieren
                                                   und Lesen der Kanaldaten */
--- a/mini/ec_mini.c	Fri Dec 23 08:23:35 2005 +0000
+++ b/mini/ec_mini.c	Thu Jan 05 13:39:39 2006 +0000
@@ -6,7 +6,7 @@
  *
  * $Id$
  *
- ******************************************************************************/
+ *****************************************************************************/
 
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -17,12 +17,12 @@
 #include "../drivers/ec_types.h"
 #include "../drivers/ec_module.h"
 
-/******************************************************************************/
+/*****************************************************************************/
 
 // Auskommentieren, wenn keine zyklischen Daten erwuenscht
 #define ECAT_CYCLIC_DATA
 
-/******************************************************************************/
+/*****************************************************************************/
 
 static EtherCAT_master_t *ecat_master = NULL;
 
@@ -30,52 +30,52 @@
 {
 #if 0
     // Block 1
-    ECAT_INIT_SLAVE(Beckhoff_EK1100),
-    ECAT_INIT_SLAVE(Beckhoff_EL4102),
-    ECAT_INIT_SLAVE(Beckhoff_EL3162),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-
-    ECAT_INIT_SLAVE(Beckhoff_EL4102),
-    ECAT_INIT_SLAVE(Beckhoff_EL4102),
-    ECAT_INIT_SLAVE(Beckhoff_EL4102),
-
-    ECAT_INIT_SLAVE(Beckhoff_EL3162),
-    ECAT_INIT_SLAVE(Beckhoff_EL3162),
-    ECAT_INIT_SLAVE(Beckhoff_EL3162),
-    ECAT_INIT_SLAVE(Beckhoff_EL3102),
-    ECAT_INIT_SLAVE(Beckhoff_EL3102),
-    ECAT_INIT_SLAVE(Beckhoff_EL3102),
+    ECAT_INIT_SLAVE(Beckhoff_EK1100, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL4102, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL3162, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+
+    ECAT_INIT_SLAVE(Beckhoff_EL4102, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL4102, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL4102, 1),
+
+    ECAT_INIT_SLAVE(Beckhoff_EL3162, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL3162, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL3162, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL3102, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL3102, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL3102, 1),
 
 #endif
 
 #if 1
     // Block 2
-    ECAT_INIT_SLAVE(Beckhoff_EK1100),
-    ECAT_INIT_SLAVE(Beckhoff_EL4102),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL3162),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL3102),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
+    ECAT_INIT_SLAVE(Beckhoff_EK1100, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL4102, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL3162, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL3102, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
 
     // Block 3
-    ECAT_INIT_SLAVE(Beckhoff_EK1100),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014)
+    ECAT_INIT_SLAVE(Beckhoff_EK1100, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1)
 #endif
 };
 
@@ -136,7 +136,7 @@
 
 static void run(unsigned long data)
 {
-    static int ms = 0;
+  static int ms = 0;
     static int cnt = 0;
     static unsigned long int k = 0;
     static int firstrun = 1;
@@ -149,37 +149,7 @@
     ms++;
     ms %= 1000;
 
-#if 0
-    ecat_tx_delay = ((unsigned int) (100000 / HZ) * (ecat_master->dev->tx_time-k))
-        / (current_cpu_data.loops_per_jiffy / 10);
-    ecat_rx_delay = ((unsigned int) (100000 / HZ) * (ecat_master->dev->rx_time-k))
-        / (current_cpu_data.loops_per_jiffy / 10);
-
-    rx_intr = ecat_master->dev->rx_intr_cnt;
-    tx_intr = ecat_master->dev->tx_intr_cnt;
-    total_intr = ecat_master->dev->intr_cnt;
-#endif
-
-    // Prozessdaten lesen
-    if (!firstrun)
-    {
-        EtherCAT_read_process_data(ecat_master);
-
-        // Daten lesen und skalieren
-//        value = EtherCAT_read_value(&ecat_master->slaves[5], 0) / 3276; //.7; FIXME kein FP im Kernel ohne Schutz !!
-//        dig1 = EtherCAT_read_value(&ecat_master->slaves[3], 0);
-    }
-    else
-        klemme = next2004(&wrap);
-
-
-#if 0
-    // Daten schreiben
-    EtherCAT_write_value(&ecat_master->slaves[4], 0, ms > 500 ? 1 : 0);
-    EtherCAT_write_value(&ecat_master->slaves[4], 1, ms > 500 ? 0 : 1);
-    EtherCAT_write_value(&ecat_master->slaves[4], 2, ms > 500 ? 0 : 1);
-    EtherCAT_write_value(&ecat_master->slaves[4], 3, ms > 500 ? 1 : 0);
-#endif
+    if (firstrun) klemme = next2004(&wrap);
 
     if (cnt++ > 20)
     {
@@ -198,20 +168,12 @@
         }
     }
 
-    if (klemme >= 0) {
-        EtherCAT_write_value(&ecat_master->slaves[klemme], kanal,up_down);
-	//printk("ECAT write: Klemme: %d, Kanal: %d, Wert: %d\n",klemme,kanal,up_down); 
-    }
-
-#if 0
-    EtherCAT_write_value(&ecat_master->slaves[13], 1, ms > 500 ? 0 : 1);
-    EtherCAT_write_value(&ecat_master->slaves[14], 2, ms > 500 ? 0 : 1);
-    EtherCAT_write_value(&ecat_master->slaves[15], 3, ms > 500 ? 1 : 0);
-#endif
-
-    // Prozessdaten schreiben
+    if (klemme >= 0)
+        EtherCAT_write_value(&ecat_slaves[klemme], kanal, up_down);
+
+    // Prozessdaten lesen und schreiben
     rdtscl(k);
-    EtherCAT_write_process_data(ecat_master);
+    EtherCAT_process_data_cycle(ecat_master, 1);
     firstrun = 0;
 
     timer.expires += HZ / 1000;
@@ -224,10 +186,12 @@
  *
  * Function: init
  *
- ******************************************************************************/
+ *****************************************************************************/
 
 int __init init_module()
 {
+    unsigned int i;
+
     printk(KERN_INFO "=== Starting Minimal EtherCAT environment... ===\n");
 
     if ((ecat_master = EtherCAT_request(0)) == NULL) {
@@ -237,17 +201,19 @@
 
     printk("Checking EtherCAT slaves.\n");
 
-    if (EtherCAT_check_slaves(ecat_master, ecat_slaves, ECAT_SLAVES_COUNT) != 0) {
+    if (EtherCAT_check_slaves(ecat_master, ecat_slaves,
+                              ECAT_SLAVES_COUNT) != 0) {
         printk(KERN_ERR "EtherCAT: Could not init slaves!\n");
         goto out_release_master;
     }
 
     printk("Activating all EtherCAT slaves.\n");
 
-    if (EtherCAT_activate_all_slaves(ecat_master) != 0)
-    {
-        printk(KERN_ERR "EtherCAT: Could not activate slaves!\n");
-        goto out_release_master;
+    for (i = 0; i < ECAT_SLAVES_COUNT; i++) {
+        if (EtherCAT_activate_slave(ecat_master, &ecat_slaves[i]) != 0) {
+            printk(KERN_ERR "EtherCAT: Could not activate slave %i!\n", i);
+            goto out_release_master;
+        }
     }
 
 #ifdef ECAT_CYCLIC_DATA
@@ -279,21 +245,25 @@
  *
  * Function: cleanup
  *
- ******************************************************************************/
+ *****************************************************************************/
 
 void __exit cleanup_module()
 {
+    unsigned int i;
+
     printk(KERN_INFO "=== Stopping Minimal EtherCAT environment... ===\n");
 
     if (ecat_master)
     {
 #ifdef ECAT_CYCLIC_DATA
         del_timer_sync(&timer);
-        EtherCAT_clear_process_data(ecat_master);
 #endif // ECAT_CYCLIC_DATA
 
         printk(KERN_INFO "Deactivating slaves.\n");
-        EtherCAT_deactivate_all_slaves(ecat_master);
+
+        for (i = 0; i < ECAT_SLAVES_COUNT; i++) {
+            EtherCAT_deactivate_slave(ecat_master, &ecat_slaves[i]);
+        }
 
         EtherCAT_release(ecat_master);
     }
@@ -311,3 +281,9 @@
 module_exit(cleanup_module);
 
 /*****************************************************************************/
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:4 ***
+;;; End: ***
+*/
--- a/rt/msr_jitter.c	Fri Dec 23 08:23:35 2005 +0000
+++ b/rt/msr_jitter.c	Thu Jan 05 13:39:39 2006 +0000
@@ -130,7 +130,6 @@
 
     int i,hit;
     static int firstrun = 1;
-    static int counter = 0;
     static unsigned long k,j = 0;
     unsigned int dt,jitter;
 
--- a/rt/msr_module.c	Fri Dec 23 08:23:35 2005 +0000
+++ b/rt/msr_module.c	Thu Jan 05 13:39:39 2006 +0000
@@ -1,43 +1,23 @@
-/**************************************************************************************************
-*
-*                          msr_module.c
-*
-*           Kernelmodul für 2.6 Kernel zur Meßdatenerfassung, Steuerung und Regelung
-*           Zeitgeber ist der Timerinterrupt (tq)
-*           
-*           Autor: Wilhelm Hagemeister
-*
-*           (C) Copyright IgH 2002
-*           Ingenieurgemeinschaft IgH
-*           Heinz-Bäcker Str. 34
-*           D-45356 Essen
-*           Tel.: +49 201/61 99 31
-*           Fax.: +49 201/61 98 36
-*           E-mail: hm@igh-essen.com
-*
-*
-*           $RCSfile: msr_module.c,v $
-*           $Revision: 1.1 $
-*           $Author: hm $
-*           $Date: 2005/11/14 20:32:57 $
-*           $State: Exp $
-*
-*
-*           $Log: msr_module.c,v $
-*           Revision 1.1  2005/11/14 20:32:57  hm
-*           Initial revision
-*
-*           Revision 1.13  2005/06/17 11:35:13  hm
-*           *** empty log message ***
-*
-*
-*           Hello Emacs: -*- c-basic-offset: 2; -*-
-*
-**************************************************************************************************/
-
-
-/*--includes-------------------------------------------------------------------------------------*/
- 
+/******************************************************************************
+ *
+ *  msr_module.c
+ *
+ *  Kernelmodul für 2.6 Kernel zur Meßdatenerfassung, Steuerung und Regelung.
+ *  Zeitgeber ist der Timerinterrupt (tq)
+ *
+ *  Autor: Wilhelm Hagemeister
+ *
+ *  (C) Copyright IgH 2002
+ *  Ingenieurgemeinschaft IgH
+ *  Heinz-Bäcker Str. 34
+ *  D-45356 Essen
+ *  Tel.: +49 201/61 99 31
+ *  Fax.: +49 201/61 98 36
+ *  E-mail: hm@igh-essen.com
+ *
+ *  $Id$
+ *
+ *****************************************************************************/
 
 #ifndef __KERNEL__
 #  define __KERNEL__
@@ -51,7 +31,7 @@
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/vmalloc.h> 
+#include <linux/vmalloc.h>
 #include <linux/fs.h>     /* everything... */
 #include <linux/proc_fs.h>
 #include <linux/time.h>
@@ -84,12 +64,9 @@
 
 #include "msr_jitter.h"
 
-MODULE_AUTHOR("Wilhelm Hagemeister, Ingenieurgemeinschaft IgH");
-MODULE_LICENSE("GPL");
-
-/*--external functions---------------------------------------------------------------------------*/
-
-/*--external data--------------------------------------------------------------------------------*/
+#define TSC2US(T) ((unsigned long) (T) * 1000UL / cpu_khz)
+
+/*--external data------------------------------------------------------------*/
 
 #define HZREDUCTION (MSR_ABTASTFREQUENZ/HZ)
 
@@ -99,12 +76,10 @@
 
 extern int proc_abtastfrequenz;
 
-/*--public data----------------------------------------------------------------------------------*/
-/*--local data-----------------------------------------------------------------------------------*/
-//struct timer_list timer;
-
-extern struct timeval process_time;           
-struct timeval msr_time_increment;                    // Increment per Interrupt
+/*--local data---------------------------------------------------------------*/
+
+extern struct timeval process_time;
+struct timeval msr_time_increment; // Increment per Interrupt
 
 //adeos
 
@@ -116,55 +91,51 @@
 
 static EtherCAT_slave_t ecat_slaves[] =
 {
-
-
 #if 1
     // Block 1
-    ECAT_INIT_SLAVE(Beckhoff_EK1100),
-    ECAT_INIT_SLAVE(Beckhoff_EL4102),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL3162),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL3102),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
+    ECAT_INIT_SLAVE(Beckhoff_EK1100, 0),
+    ECAT_INIT_SLAVE(Beckhoff_EL4102, 0),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 0),
+    ECAT_INIT_SLAVE(Beckhoff_EL3162, 0),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 0),
+    ECAT_INIT_SLAVE(Beckhoff_EL3102, 0),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 0),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 0),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 0),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 0),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 0),
 
     // Block 2
-    ECAT_INIT_SLAVE(Beckhoff_EK1100),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL2004),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014),
-    ECAT_INIT_SLAVE(Beckhoff_EL1014)
-#endif
-
-#if 1
+    ECAT_INIT_SLAVE(Beckhoff_EK1100, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL2004, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1),
+    ECAT_INIT_SLAVE(Beckhoff_EL1014, 1)
+#endif
+
+#if 0
     // Block 3
-   ,ECAT_INIT_SLAVE(Beckhoff_EK1100),
-    ECAT_INIT_SLAVE(Beckhoff_EL3162),
-    ECAT_INIT_SLAVE(Beckhoff_EL3162),
-    ECAT_INIT_SLAVE(Beckhoff_EL3162),
-    ECAT_INIT_SLAVE(Beckhoff_EL3162),
-    ECAT_INIT_SLAVE(Beckhoff_EL3102),
-    ECAT_INIT_SLAVE(Beckhoff_EL3102),
-    ECAT_INIT_SLAVE(Beckhoff_EL3102),
-    ECAT_INIT_SLAVE(Beckhoff_EL4102),
-    ECAT_INIT_SLAVE(Beckhoff_EL4102),
-    ECAT_INIT_SLAVE(Beckhoff_EL4102),
-    ECAT_INIT_SLAVE(Beckhoff_EL4102),
-    ECAT_INIT_SLAVE(Beckhoff_EL4132)
-
-
+   ,ECAT_INIT_SLAVE(Beckhoff_EK1100, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL3162, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL3162, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL3162, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL3162, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL3102, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL3102, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL3102, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL4102, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL4102, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL4102, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL4102, 2),
+    ECAT_INIT_SLAVE(Beckhoff_EL4132, 2)
 #endif
 };
 
@@ -183,8 +154,6 @@
  *
  *****************************************************************************/
 
-
-
 static int next2004(int *wrap)
 {
     static int i = 0;
@@ -228,23 +197,17 @@
     static int up_down = 0;
     int wrap = 0;
 
+    static unsigned int debug_counter = 0;
+    unsigned long t1, t2, t3, t4, t5, t6, t7;
+    static unsigned long lt = 0;
+    unsigned int tr1, tr2;
+
+    rdtscl(t1);
 
     // Prozessdaten lesen
     msr_jitter_run(MSR_ABTASTFREQUENZ);
 
-    if (!firstrun)
-    {
-        EtherCAT_read_process_data(ecat_master);
-
-        // Daten lesen und skalieren
-#ifdef USE_MSR_LIB
-        value = EtherCAT_read_value(&ecat_master->slaves[5], 0) / 3276.0; 
-        dig1 = EtherCAT_read_value(&ecat_master->slaves[2], 0);
-#endif
-    }
-    else
-        klemme = next2004(&wrap);
-
+    if (firstrun) klemme = next2004(&wrap);
 
     ms++;
     ms %= 1000;
@@ -266,8 +229,7 @@
     }
 
     if (klemme >= 0) {
-        EtherCAT_write_value(&ecat_master->slaves[klemme], kanal,up_down);
-	//printk("ECAT write: Klemme: %d, Kanal: %d, Wert: %d\n",klemme,kanal,up_down); 
+        EtherCAT_write_value(&ecat_slaves[klemme], kanal, up_down);
     }
 
 #if 0
@@ -278,32 +240,63 @@
 
     // Prozessdaten schreiben
     rdtscl(k);
-    EtherCAT_write_process_data(ecat_master);
+    rdtscl(t2);
+
+    EtherCAT_process_data_cycle(ecat_master, 0);
+
+    t3 = ecat_master->tx_time;
+    t4 = ecat_master->rx_time;
+    tr1 = ecat_master->rx_tries;
+
+    EtherCAT_process_data_cycle(ecat_master, 1);
+
+    t5 = ecat_master->tx_time;
+    t6 = ecat_master->rx_time;
+    tr2 = ecat_master->rx_tries;
+
+    //EtherCAT_process_data_cycle(ecat_master, 2);
+
+    // Daten lesen und skalieren
+#ifdef USE_MSR_LIB
+    value = EtherCAT_read_value(&ecat_slaves[5], 0) / 3276.0;
+    dig1 = EtherCAT_read_value(&ecat_slaves[2], 0);
+#endif
+
+    rdtscl(t7);
+
+    if (debug_counter == MSR_ABTASTFREQUENZ) {
+      printk(KERN_DEBUG "%lu: %luŽµs + %luŽµs + %luŽµs + %luŽµs + %luŽµs +"
+             " %luŽµs = %luŽµs (%u %u)\n",
+             TSC2US(t1 - lt),
+             TSC2US(t2 - t1), TSC2US(t3 - t2), TSC2US(t4 - t3),
+             TSC2US(t5 - t4), TSC2US(t6 - t5), TSC2US(t7 - t6),
+             TSC2US(t7 - t1), tr1, tr2);
+      debug_counter = 0;
+    }
+
+    lt = t1;
+
     firstrun = 0;
-
-}
-
-/*
-***************************************************************************************************
-*
-* Function: msr_run(_interrupt)
-*
-* Beschreibung: Routine wird zyklisch im Timerinterrupt ausgeführt
-*               (hier muß alles rein, was Echtzeit ist ...)
-*
-* Parameter: Zeiger auf msr_data
-*
-* Rückgabe:
-*
-* Status: exp
-*
-***************************************************************************************************
-*/
-
+    debug_counter++;
+}
+
+/******************************************************************************
+ *
+ *  Function: msr_run(_interrupt)
+ *
+ *  Beschreibung: Routine wird zyklisch im Timerinterrupt ausgeführt
+ *                (hier muß alles rein, was Echtzeit ist ...)
+ *
+ *  Parameter: Zeiger auf msr_data
+ *
+ *  Rückgabe:
+ *
+ *  Status: exp
+ *
+ *****************************************************************************/
 
 void msr_run(unsigned irq)
 {
-
   static int counter = 0;
 #ifdef USE_MSR_LIB
 
@@ -318,45 +311,40 @@
 #endif
     /* und wieder in die Timerliste eintragen */
     /* und neu in die Taskqueue eintragen */
-//    timer.expires += 1;
-//    add_timer(&timer);
+    //timer.expires += 1;
+    //add_timer(&timer);
 
     ipipe_control_irq(irq,0,IPIPE_ENABLE_MASK);  //Interrupt bestŽätigen
     if(counter++ > HZREDUCTION) {
 	ipipe_propagate_irq(irq);  //und weiterreichen
 	counter = 0;
     }
-
-
-}
-
-void domain_entry (void) {
-    printk("Domain %s started.\n",	ipipe_current_domain->name);
-
+}
+
+void domain_entry (void)
+{
+    printk("Domain %s started.\n", ipipe_current_domain->name);
 
     ipipe_get_sysinfo(&sys_info);
     ipipe_virtualize_irq(ipipe_current_domain,sys_info.archdep.tmirq,
 			 &msr_run, NULL, IPIPE_HANDLE_MASK);
 
-    ipipe_tune_timer(1000000000UL/MSR_ABTASTFREQUENZ,0); 
-
-}
-
-/*
-*******************************************************************************
-*
-* Function: msr_register_channels
-*
-* Beschreibung: KanŽäle registrieren
-*
-* Parameter:
-*
-* RŽückgabe: 
-*               
-* Status: exp
-*
-*******************************************************************************
-*/
+    ipipe_tune_timer(1000000000UL/MSR_ABTASTFREQUENZ,0);
+}
+
+/******************************************************************************
+ *
+ *  Function: msr_register_channels
+ *
+ *  Beschreibung: KanŽäle registrieren
+ *
+ *  Parameter:
+ *
+ *  RŽückgabe:
+ *
+ *  Status: exp
+ *
+ *****************************************************************************/
 
 int msr_globals_register(void)
 {
@@ -364,23 +352,23 @@
     msr_reg_kanal("/value", "V", &value, TDBL);
     msr_reg_kanal("/dig1", "", &dig1, TINT);
 #endif
-/*  msr_reg_kanal("/Taskinfo/Ecat/TX-Delay","us",&ecat_tx_delay,TUINT);
-  msr_reg_kanal("/Taskinfo/Ecat/RX-Delay","us",&ecat_rx_delay,TUINT);
-  msr_reg_kanal("/Taskinfo/Ecat/TX-Cnt","",&tx_intr,TUINT);
-  msr_reg_kanal("/Taskinfo/Ecat/RX-Cnt","",&rx_intr,TUINT);
-  msr_reg_kanal("/Taskinfo/Ecat/Total-Cnt","",&total_intr,TUINT);
-*/
+#if 0
+    msr_reg_kanal("/Taskinfo/Ecat/TX-Delay","us",&ecat_tx_delay,TUINT);
+    msr_reg_kanal("/Taskinfo/Ecat/RX-Delay","us",&ecat_rx_delay,TUINT);
+    msr_reg_kanal("/Taskinfo/Ecat/TX-Cnt","",&tx_intr,TUINT);
+    msr_reg_kanal("/Taskinfo/Ecat/RX-Cnt","",&rx_intr,TUINT);
+    msr_reg_kanal("/Taskinfo/Ecat/Total-Cnt","",&total_intr,TUINT);
+#endif
   return 0;
 }
 
-
-/****************************************************************************************************
+/******************************************************************************
  * the init/clean material
- ****************************************************************************************************/
-
+ *****************************************************************************/
 
 int __init init_module()
 {
+    unsigned int i;
     struct ipipe_domain_attr attr; //ipipe
 
     // Als allererstes die RT-lib initialisieren
@@ -409,9 +397,10 @@
 
     printk("Activating all EtherCAT slaves.\n");
 
-    if (EtherCAT_activate_all_slaves(ecat_master) != 0) {
-        printk(KERN_ERR "EtherCAT: Could not activate slaves!\n");
-        goto out_release_master;
+    for (i = 0; i < ECAT_SLAVES_COUNT; i++) {
+        if (EtherCAT_activate_slave(ecat_master, ecat_slaves + i) < 0) {
+            goto out_release_master;
+        }
     }
 
     do_gettimeofday(&process_time);
@@ -436,11 +425,12 @@
     return -1;
 }
 
-
-//****************************************************************************
+/*****************************************************************************/
+
 void __exit cleanup_module()
-
-{
+{
+    unsigned int i;
+
     msr_print_info("msk_modul: unloading...");
 
     ipipe_tune_timer(1000000000UL/HZ,0); //alten Timertakt wieder herstellen
@@ -450,9 +440,14 @@
 
     if (ecat_master)
     {
-        EtherCAT_clear_process_data(ecat_master);
         printk(KERN_INFO "Deactivating slaves.\n");
-        EtherCAT_deactivate_all_slaves(ecat_master);
+
+        for (i = 0; i < ECAT_SLAVES_COUNT; i++) {
+            if (EtherCAT_deactivate_slave(ecat_master, ecat_slaves + i) < 0) {
+                printk(KERN_WARNING "Warning - Could not deactivate slave!\n");
+            }
+        }
+
         EtherCAT_release(ecat_master);
     }
 
@@ -463,6 +458,8 @@
 #endif
 }
 
+/*****************************************************************************/
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR ("Wilhelm Hagemeister <hm@igh-essen.com>");
 MODULE_DESCRIPTION ("EtherCAT test environment");
@@ -470,18 +467,4 @@
 module_init(init_module);
 module_exit(cleanup_module);
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+/*****************************************************************************/
--- a/rt/msr_param.h	Fri Dec 23 08:23:35 2005 +0000
+++ b/rt/msr_param.h	Thu Jan 05 13:39:39 2006 +0000
@@ -1,6 +1,6 @@
 #ifndef _MSR_PARAM_H_
 #define _MSR_PARAM_H_
-#define  MSR_ABTASTFREQUENZ 20000   //FIXME nur für den Simulator, der virtuelle 10 Mal schneller läuft ....HZ  /* Abtastrate der Kan%/1€Œiso8859-15äle in [HZ]*/
+#define  MSR_ABTASTFREQUENZ 10000   //FIXME nur für den Simulator, der virtuelle 10 Mal schneller läuft ....HZ  /* Abtastrate der Kan%/1€Œiso8859-15äle in [HZ]*/
 
 #endif