Dynamische FMMU-Konfiguration, zwei Kopieroperationen eingespart, Einr?ckungen angepasst.
authorFlorian Pose <fp@igh-essen.com>
Thu, 23 Feb 2006 09:58:50 +0000
changeset 73 9f4ea66d89a3
parent 72 7c986b717411
child 74 9bf603942791
Dynamische FMMU-Konfiguration, zwei Kopieroperationen eingespart, Einr?ckungen angepasst.
Makefile
TODO
devices/8139too.c
include/EtherCAT_dev.h
include/EtherCAT_rt.h
master/Makefile
master/canopen.c
master/canopen.h
master/command.c
master/command.h
master/device.c
master/device.h
master/domain.c
master/domain.h
master/frame.c
master/frame.h
master/globals.h
master/master.c
master/master.h
master/module.c
master/slave.c
master/slave.h
master/types.c
master/types.h
mini/mini.c
rt/Makefile
rt/msr_jitter.c
rt/msr_jitter.h
rt/msr_module.c
--- a/Makefile	Wed Feb 22 17:36:28 2006 +0000
+++ b/Makefile	Thu Feb 23 09:58:50 2006 +0000
@@ -42,6 +42,6 @@
 	@echo >> $(CONFIG_FILE)
 	@echo "$(CONFIG_FILE) erstellt."
 
-#----------------------------------------------------------------
+#------------------------------------------------------------------------------
 
 endif
--- a/TODO	Wed Feb 22 17:36:28 2006 +0000
+++ b/TODO	Thu Feb 23 09:58:50 2006 +0000
@@ -7,4 +7,5 @@
 - Ethernet over EtherCAT (EoE)
 - eepro100-Kartentreiber
 - Proc/SysFS-Interface mit Baumdarstellung des Busses
+- Anzahl unterstützter Sync-Manager/FMMUs auslesen
 
--- a/devices/8139too.c	Wed Feb 22 17:36:28 2006 +0000
+++ b/devices/8139too.c	Thu Feb 23 09:58:50 2006 +0000
@@ -2268,14 +2268,12 @@
                 }
                 else
                 {
-                  if (EtherCAT_dev_receive(rtl_ec_dev,
-                                           &rx_ring[ring_offset + 4] + ETH_HLEN,
-                                           pkt_size - ETH_HLEN) == 0)
-                  {
+                    EtherCAT_dev_receive(rtl_ec_dev,
+                                         &rx_ring[ring_offset + 4] + ETH_HLEN,
+                                         pkt_size - ETH_HLEN);
                     dev->last_rx = jiffies;
                     tp->stats.rx_bytes += pkt_size;
                     tp->stats.rx_packets++;
-                  }
                 }
 
                 /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@@ -2466,7 +2464,7 @@
           else
           {
             /* Beim EtherCAT-Device einfach alle Frames empfangen */
-            rtl8139_rx(dev, tp, 100); // FIXME Das ist echt dirty...
+            rtl8139_rx(dev, tp, 100); // FIXME
           }
 	}
 
--- a/include/EtherCAT_dev.h	Wed Feb 22 17:36:28 2006 +0000
+++ b/include/EtherCAT_dev.h	Thu Feb 23 09:58:50 2006 +0000
@@ -21,8 +21,11 @@
 
 typedef enum
 {
-  EC_DEVICE_STATE_READY, EC_DEVICE_STATE_SENT, EC_DEVICE_STATE_RECEIVED,
-  EC_DEVICE_STATE_TIMEOUT, EC_DEVICE_STATE_ERROR
+  EC_DEVICE_STATE_READY = 0,
+  EC_DEVICE_STATE_SENT,
+  EC_DEVICE_STATE_RECEIVED,
+  EC_DEVICE_STATE_TIMEOUT,
+  EC_DEVICE_STATE_ERROR
 }
 ec_device_state_t;
 
@@ -33,9 +36,10 @@
                                                    struct pt_regs *),
                                    struct module *);
 void EtherCAT_dev_unregister(unsigned int, ec_device_t *);
+
 int EtherCAT_dev_is_ec(ec_device_t *, struct net_device *);
 void EtherCAT_dev_state(ec_device_t *, ec_device_state_t);
-int EtherCAT_dev_receive(ec_device_t *, void *, unsigned int);
+void EtherCAT_dev_receive(ec_device_t *, void *, unsigned int);
 
 /*****************************************************************************/
 
--- a/include/EtherCAT_rt.h	Wed Feb 22 17:36:28 2006 +0000
+++ b/include/EtherCAT_rt.h	Thu Feb 23 09:58:50 2006 +0000
@@ -14,106 +14,83 @@
 struct ec_master;
 typedef struct ec_master ec_master_t;
 
-struct ec_slave_type;
-typedef struct ec_slave_type ec_slave_type_t;
+struct ec_domain;
+typedef struct ec_domain ec_domain_t;
 
 struct ec_slave;
 typedef struct ec_slave ec_slave_t;
 
-struct ec_slave_init;
-typedef struct ec_slave_init ec_slave_init_t;
+typedef enum
+{
+    ec_sync,
+    ec_async
+}
+ec_domain_mode_t;
+
+typedef enum
+{
+    ec_status,
+    ec_control,
+    ec_ipvalue,
+    ec_opvalue
+}
+ec_field_type_t;
+
+typedef struct
+{
+    void **data;
+    const char *address;
+    const char *vendor;
+    const char *product;
+    ec_field_type_t field_type;
+    unsigned int field_index;
+    unsigned int field_count;
+}
+ec_field_init_t;
 
 /*****************************************************************************/
+// Master request functions
 
 ec_master_t *EtherCAT_rt_request_master(unsigned int master_index);
 
 void EtherCAT_rt_release_master(ec_master_t *master);
 
-ec_slave_t *EtherCAT_rt_register_slave(ec_master_t *master,
-                                       const char *address,
-                                       const char *vendor_name,
-                                       const char *product_name,
-                                       int domain);
+/*****************************************************************************/
+// Master methods
 
-int EtherCAT_rt_register_slave_list(ec_master_t *master,
-                                    const ec_slave_init_t *slaves,
-                                    unsigned int count);
+ec_domain_t *EtherCAT_rt_master_register_domain(ec_master_t *master,
+                                                ec_domain_mode_t mode,
+                                                unsigned int timeout_us);
 
-int EtherCAT_rt_activate_slaves(ec_master_t *master);
+int EtherCAT_rt_master_activate(ec_master_t *master);
 
-int EtherCAT_rt_deactivate_slaves(ec_master_t *master);
+int EtherCAT_rt_master_deactivate(ec_master_t *master);
 
-int EtherCAT_rt_domain_xio(ec_master_t *master, unsigned int domain,
-                           unsigned int timeout_us);
+void EtherCAT_rt_master_debug(ec_master_t *master, int level);
+void EtherCAT_rt_master_print(const ec_master_t *master);
 
-void EtherCAT_rt_debug_level(ec_master_t *master, int level);
+/*****************************************************************************/
+// Domain Methods
 
-int EtherCAT_rt_canopen_sdo_write(ec_master_t *master, ec_slave_t *slave,
+ec_slave_t *EtherCAT_rt_register_slave_field(ec_domain_t *domain,
+                                             const char *address,
+                                             const char *vendor_name,
+                                             const char *product_name,
+                                             void **data_ptr,
+                                             ec_field_type_t field_type,
+                                             unsigned int field_index,
+                                             unsigned int field_count);
+
+int EtherCAT_rt_domain_xio(ec_domain_t *domain);
+
+/*****************************************************************************/
+// Slave Methods
+
+int EtherCAT_rt_canopen_sdo_write(ec_slave_t *slave,
                                   unsigned int sdo_index,
                                   unsigned char sdo_subindex,
-                                  unsigned int value, unsigned int size);
-
-/*****************************************************************************/
-
-/**
-   EtherCAT-Slave
-*/
-
-struct ec_slave
-{
-    // Base data
-    unsigned char base_type; /**< Slave-Typ */
-    unsigned char base_revision; /**< Revision */
-    unsigned short base_build; /**< Build-Nummer */
-
-    // Addresses
-    short ring_position; /**< (Negative) Position des Slaves im Bus */
-    unsigned short station_address; /**< Konfigurierte Slave-Adresse */
-
-    // Slave information interface
-    unsigned int sii_vendor_id; /**< Identifikationsnummer des Herstellers */
-    unsigned int sii_product_code; /**< Herstellerspezifischer Produktcode */
-    unsigned int sii_revision_number; /**< Revisionsnummer */
-    unsigned int sii_serial_number; /**< Seriennummer der Klemme */
-
-    const ec_slave_type_t *type; /**< Zeiger auf die Beschreibung
-                                    des Slave-Typs */
-
-    unsigned int logical_address; /**< Konfigurierte, logische Adresse */
-
-    void *process_data; /**< Zeiger auf den Speicherbereich
-                           innerhalb eines Prozessdatenobjekts */
-    void *private_data; /**< Zeiger auf privaten Datenbereich */
-    int (*configure)(ec_slave_t *); /**< Zeiger auf die Funktion zur
-                                     Konfiguration */
-
-    unsigned char registered; /**< Der Slave wurde registriert */
-
-    unsigned int domain; /**< Prozessdatendomäne */
-
-    int error_reported; /**< Ein Zugriffsfehler wurde bereits gemeldet */
-};
-
-/*****************************************************************************/
-
-/**
-   Beschreibung eines EtherCAT-Slave-Typs.
-
-   Diese Beschreibung dient zur Konfiguration einer bestimmten
-   Slave-Art. Sie enthält die Konfigurationsdaten für die
-   Slave-internen Sync-Manager und FMMU's.
-*/
-
-struct ec_slave_init
-{
-    ec_slave_t **slave_ptr; /**< Zeiger auf den Slave-Zeiger, der später auf
-                               die Slave-Struktur zeigen soll. */
-    const char *address; /**< ASCII-kodierte Bus-Adresse des zu
-                            registrierenden Slaves \sa ec_address */
-    const char *vendor_name; /**< Name des Herstellers */
-    const char *product_name; /**< Name des Slaves-Typs */
-    unsigned int domain; /**< Domäne, in der registriert werden soll. */
-};
+                                  unsigned int value,
+                                  unsigned int size);
 
 /*****************************************************************************/
 
--- a/master/Makefile	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/Makefile	Thu Feb 23 09:58:50 2006 +0000
@@ -15,7 +15,7 @@
 
 obj-m := ec_master.o
 
-ec_master-objs := module.o master.o device.o slave.o command.o types.o \
+ec_master-objs := module.o master.o device.o slave.o frame.o types.o \
 			domain.o canopen.o
 
 REV = `svnversion $(src)`
--- a/master/canopen.c	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/canopen.c	Thu Feb 23 09:58:50 2006 +0000
@@ -18,16 +18,26 @@
 
 /*****************************************************************************/
 
-int EtherCAT_rt_canopen_sdo_write(ec_master_t *master, ec_slave_t *slave,
-                                  unsigned int sdo_index,
-                                  unsigned char sdo_subindex,
-                                  unsigned int value, unsigned int size)
+/**
+   Schreibt ein CANopen-SDO (service data object).
+ */
+
+int EtherCAT_rt_canopen_sdo_write(
+    ec_slave_t *slave, /**< EtherCAT-Slave */
+    unsigned int sdo_index, /**< SDO-Index */
+    unsigned char sdo_subindex, /**< SDO-Subindex */
+    unsigned int value, /**< Neuer Wert */
+    unsigned int size /**< Größe des Datenfeldes */
+    )
 {
     unsigned char data[0xF6];
-    ec_command_t cmd;
+    ec_frame_t frame;
     unsigned int tries_left, i;
+    ec_master_t *master;
 
-    for (i = 0; i < 0xF6; i++) data[i] = 0x00;
+    memset(data, 0x00, 0xF6);
+
+    master = slave->master;
 
     if (size == 0 || size > 4) {
         printk(KERN_ERR "EtherCAT: Illegal SDO data size: %i!\n", size);
@@ -55,14 +65,14 @@
         value >>= 8;
     }
 
-    ec_command_write(&cmd, slave->station_address, 0x1800, 0xF6, data);
+    ec_frame_init_npwr(&frame, master, slave->station_address, 0x1800, 0xF6,
+                       data);
 
-    if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-        return -1;
+    if (unlikely(ec_frame_send_receive(&frame) < 0)) return -1;
 
-    if (unlikely(cmd.working_counter != 1)) {
+    if (unlikely(frame.working_counter != 1)) {
         printk(KERN_ERR "EtherCAT: Mailbox send - Slave %i did not respond!\n",
-               slave->ring_position * (-1));
+               slave->ring_position);
         return -1;
     }
 
@@ -71,18 +81,17 @@
     tries_left = 10;
     while (tries_left)
     {
-        ec_command_read(&cmd, slave->station_address, 0x808, 8);
+        ec_frame_init_nprd(&frame, master, slave->station_address, 0x808, 8);
 
-        if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-            return -1;
+        if (unlikely(ec_frame_send_receive(&frame) < 0)) return -1;
 
-        if (unlikely(cmd.working_counter != 1)) {
+        if (unlikely(frame.working_counter != 1)) {
             printk(KERN_ERR "EtherCAT: Mailbox check - Slave %i did not"
-                   " respond!\n", slave->ring_position * (-1));
+                   " respond!\n", slave->ring_position);
             return -1;
         }
 
-        if (cmd.data[5] & 8) { // Written bit is high
+        if (frame.data[5] & 8) { // Written bit is high
             break;
         }
 
@@ -92,30 +101,29 @@
 
     if (!tries_left) {
         printk(KERN_ERR "EtherCAT: Mailbox check - Slave %i timed out.\n",
-               slave->ring_position * (-1));
+               slave->ring_position);
         return -1;
     }
 
-    ec_command_read(&cmd, slave->station_address, 0x18F6, 0xF6);
+    ec_frame_init_nprd(&frame, master, slave->station_address, 0x18F6, 0xF6);
 
-    if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-        return -1;
+    if (unlikely(ec_frame_send_receive(&frame) < 0)) return -1;
 
-    if (unlikely(cmd.working_counter != 1)) {
+    if (unlikely(frame.working_counter != 1)) {
         printk(KERN_ERR "EtherCAT: Mailbox receive - Slave %i did not"
-               " respond!\n", slave->ring_position * (-1));
+               " respond!\n", slave->ring_position);
         return -1;
     }
 
-    if (cmd.data[5] != 0x03 // COE
-        || (cmd.data[7] >> 4) != 0x03 // SDO response
-        || (cmd.data[8] >> 5) != 0x03 // Initiate download response
-        || (cmd.data[9] != (sdo_index & 0xFF)) // Index
-        || (cmd.data[10] != ((sdo_index >> 8) & 0xFF))
-        || (cmd.data[11] != sdo_subindex)) // Subindex
+    if (frame.data[5] != 0x03 // COE
+        || (frame.data[7] >> 4) != 0x03 // SDO response
+        || (frame.data[8] >> 5) != 0x03 // Initiate download response
+        || (frame.data[9] != (sdo_index & 0xFF)) // Index
+        || (frame.data[10] != ((sdo_index >> 8) & 0xFF))
+        || (frame.data[11] != sdo_subindex)) // Subindex
     {
         printk(KERN_ERR "EtherCAT: Illegal mailbox response at slave %i!\n",
-               slave->ring_position * (-1));
+               slave->ring_position);
         return -1;
     }
 
--- a/master/canopen.h	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/canopen.h	Thu Feb 23 09:58:50 2006 +0000
@@ -17,3 +17,9 @@
 /*****************************************************************************/
 
 #endif
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:4 ***
+;;; End: ***
+*/
--- a/master/command.c	Wed Feb 22 17:36:28 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +0,0 @@
-/******************************************************************************
- *
- *  c o m m a n d . c
- *
- *  Methoden für ein EtherCAT-Kommando.
- *
- *  $Id$
- *
- *****************************************************************************/
-
-#include <linux/slab.h>
-
-#include "command.h"
-
-/*****************************************************************************/
-
-/**
-   Kommando-Konstruktor.
-
-   Initialisiert alle Variablen innerhalb des Kommandos auf die
-   Default-Werte.
-
-   @param cmd Zeiger auf das zu initialisierende Kommando.
-*/
-
-void ec_command_init(ec_command_t *cmd)
-{
-  cmd->type = EC_COMMAND_NONE;
-  cmd->address.logical = 0x00000000;
-  cmd->data_length = 0;
-  cmd->state = EC_COMMAND_STATE_READY;
-  cmd->index = 0;
-  cmd->working_counter = 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Kommando-Destruktor.
-
-   Setzt alle Attribute auf den Anfangswert zurueck.
-
-   @param cmd Zeiger auf das zu initialisierende Kommando.
-*/
-
-void ec_command_clear(ec_command_t *cmd)
-{
-  ec_command_init(cmd);
-}
-
-/*****************************************************************************/
-
-#define EC_FUNC_HEADER \
-  ec_command_init(cmd)
-
-#define EC_FUNC_WRITE_FOOTER \
-  cmd->data_length = length; \
-  memcpy(cmd->data, data, length);
-
-#define EC_FUNC_READ_FOOTER \
-  cmd->data_length = length;
-
-/*****************************************************************************/
-
-/**
-   Initialisiert ein EtherCAT-NPRD-Kommando.
-
-   @param cmd Zeiger auf das Kommando
-   @param node_address Adresse des Knotens (Slaves)
-   @param offset Physikalische Speicheradresse im Slave
-   @param length Länge der zu lesenden Daten
-*/
-
-void ec_command_read(ec_command_t *cmd, unsigned short node_address,
-                     unsigned short offset, unsigned int length)
-{
-  if (unlikely(node_address == 0x0000))
-    printk(KERN_WARNING "EtherCAT: Warning - Using node address 0x0000!\n");
-
-  EC_FUNC_HEADER;
-
-  cmd->type = EC_COMMAND_NPRD;
-  cmd->address.phy.dev.node = node_address;
-  cmd->address.phy.mem = offset;
-
-  EC_FUNC_READ_FOOTER;
-}
-
-/*****************************************************************************/
-
-/**
-   Initialisiert ein EtherCAT-NPWR-Kommando.
-
-   Alloziert ein "node-adressed physical write"-Kommando
-   und fügt es in die Liste des Masters ein.
-
-   @param cmd Zeiger auf das Kommando
-   @param node_address Adresse des Knotens (Slaves)
-   @param offset Physikalische Speicheradresse im Slave
-   @param length Länge der zu schreibenden Daten
-   @param data Zeiger auf Speicher mit zu schreibenden Daten
-*/
-
-void ec_command_write(ec_command_t *cmd, unsigned short node_address,
-                      unsigned short offset, unsigned int length,
-                      const unsigned char *data)
-{
-  if (unlikely(node_address == 0x0000))
-    printk(KERN_WARNING "EtherCAT: Warning - Using node address 0x0000!\n");
-
-  EC_FUNC_HEADER;
-
-  cmd->type = EC_COMMAND_NPWR;
-  cmd->address.phy.dev.node = node_address;
-  cmd->address.phy.mem = offset;
-
-  EC_FUNC_WRITE_FOOTER;
-}
-
-/*****************************************************************************/
-
-/**
-   Initialisiert ein EtherCAT-APRD-Kommando.
-
-   Alloziert ein "autoincerement physical read"-Kommando
-   und fügt es in die Liste des Masters ein.
-
-   @param cmd Zeiger auf das Kommando
-   @param ring_position (Negative) Position des Slaves im Bus
-   @param offset Physikalische Speicheradresse im Slave
-   @param length Länge der zu lesenden Daten
-*/
-
-void ec_command_position_read(ec_command_t *cmd, short ring_position,
-                              unsigned short offset, unsigned int length)
-{
-  EC_FUNC_HEADER;
-
-  cmd->type = EC_COMMAND_APRD;
-  cmd->address.phy.dev.pos = ring_position;
-  cmd->address.phy.mem = offset;
-
-  EC_FUNC_READ_FOOTER;
-}
-
-/*****************************************************************************/
-
-/**
-   Initialisiert ein EtherCAT-APWR-Kommando.
-
-   Alloziert ein "autoincrement physical write"-Kommando
-   und fügt es in die Liste des Masters ein.
-
-   @param cmd Zeiger auf das Kommando
-   @param ring_position (Negative) Position des Slaves im Bus
-   @param offset Physikalische Speicheradresse im Slave
-   @param length Länge der zu schreibenden Daten
-   @param data Zeiger auf Speicher mit zu schreibenden Daten
-*/
-
-void ec_command_position_write(ec_command_t *cmd, short ring_position,
-                               unsigned short offset, unsigned int length,
-                               const unsigned char *data)
-{
-  EC_FUNC_HEADER;
-
-  cmd->type = EC_COMMAND_APWR;
-  cmd->address.phy.dev.pos = ring_position;
-  cmd->address.phy.mem = offset;
-
-  EC_FUNC_WRITE_FOOTER;
-}
-
-/*****************************************************************************/
-
-/**
-   Initialisiert ein EtherCAT-BRD-Kommando.
-
-   Alloziert ein "broadcast read"-Kommando
-   und fügt es in die Liste des Masters ein.
-
-   @param cmd Zeiger auf das Kommando
-   @param offset Physikalische Speicheradresse im Slave
-   @param length Länge der zu lesenden Daten
-*/
-
-void ec_command_broadcast_read(ec_command_t *cmd, unsigned short offset,
-                               unsigned int length)
-{
-  EC_FUNC_HEADER;
-
-  cmd->type = EC_COMMAND_BRD;
-  cmd->address.phy.dev.node = 0x0000;
-  cmd->address.phy.mem = offset;
-
-  EC_FUNC_READ_FOOTER;
-}
-
-/*****************************************************************************/
-
-/**
-   Initialisiert ein EtherCAT-BWR-Kommando.
-
-   Alloziert ein "broadcast write"-Kommando
-   und fügt es in die Liste des Masters ein.
-
-   @param cmd Zeiger auf das Kommando
-   @param offset Physikalische Speicheradresse im Slave
-   @param length Länge der zu schreibenden Daten
-   @param data Zeiger auf Speicher mit zu schreibenden Daten
-*/
-
-void ec_command_broadcast_write(ec_command_t *cmd, unsigned short offset,
-                                unsigned int length, const unsigned char *data)
-{
-  EC_FUNC_HEADER;
-
-  cmd->type = EC_COMMAND_BWR;
-  cmd->address.phy.dev.node = 0x0000;
-  cmd->address.phy.mem = offset;
-
-  EC_FUNC_WRITE_FOOTER;
-}
-
-/*****************************************************************************/
-
-/**
-   Initialisiert ein EtherCAT-LRW-Kommando.
-
-   Alloziert ein "logical read write"-Kommando
-   und fügt es in die Liste des Masters ein.
-
-   @param cmd Zeiger auf das Kommando
-   @param offset Logische Speicheradresse
-   @param length Länge der zu lesenden/schreibenden Daten
-   @param data Zeiger auf Speicher mit zu lesenden/schreibenden Daten
-*/
-
-void ec_command_logical_read_write(ec_command_t *cmd, unsigned int offset,
-                                   unsigned int length, unsigned char *data)
-{
-  EC_FUNC_HEADER;
-
-  cmd->type = EC_COMMAND_LRW;
-  cmd->address.logical = offset;
-
-  EC_FUNC_WRITE_FOOTER;
-}
-
-/*****************************************************************************/
--- a/master/command.h	Wed Feb 22 17:36:28 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/******************************************************************************
- *
- *  c o m m a n d . h
- *
- *  Struktur für ein EtherCAT-Kommando.
- *
- *  $Id$
- *
- *****************************************************************************/
-
-#ifndef _EC_COMMAND_H_
-#define _EC_COMMAND_H_
-
-#include "globals.h"
-
-/*****************************************************************************/
-
-/**
-   Status eines EtherCAT-Kommandos.
-*/
-
-typedef enum
-{
-  EC_COMMAND_STATE_READY, EC_COMMAND_STATE_SENT, EC_COMMAND_STATE_RECEIVED
-}
-ec_command_state_t;
-
-/*****************************************************************************/
-
-/**
-   EtherCAT-Adresse.
-
-   Im EtherCAT-Rahmen sind 4 Bytes für die Adresse reserviert, die je nach
-   Kommandotyp, eine andere Bedeutung haben können: Bei Autoinkrementbefehlen
-   sind die ersten zwei Bytes die (negative) Autoinkrement-Adresse, bei Knoten-
-   adressierten Befehlen entsprechen sie der Knotenadresse. Das dritte und
-   vierte Byte entspricht in diesen Fällen der physikalischen Speicheradresse
-   auf dem Slave. Bei einer logischen Adressierung entsprechen alle vier Bytes
-   der logischen Adresse.
-*/
-
-typedef union
-{
-  struct
-  {
-    union
-    {
-      short pos; /**< (Negative) Ring-Position des Slaves */
-      unsigned short node; /**< Konfigurierte Knotenadresse */
-    }
-    dev;
-
-    unsigned short mem; /**< Physikalische Speicheradresse im Slave */
-  }
-  phy; /**< Physikalische Adresse */
-
-  unsigned long logical; /**< Logische Adresse */
-  unsigned char raw[4]; /**< Rohdaten für die Generierung des Frames */
-}
-ec_address_t;
-
-/*****************************************************************************/
-
-/**
-   EtherCAT-Kommando.
-*/
-
-typedef struct ec_command
-{
-  ec_command_type_t type; /**< Typ des Kommandos (APRD, NPWR, etc) */
-  ec_address_t address; /**< Adresse des/der Empfänger */
-  unsigned int data_length; /**< Länge der zu sendenden und/oder
-                               empfangenen Daten */
-  ec_command_state_t state; /**< Zustand des Kommandos
-                           (bereit, gesendet, etc) */
-  unsigned char index; /**< Kommando-Index, mit der das Kommando gesendet
-                          wurde (wird vom Master beim Senden gesetzt. */
-  unsigned int working_counter; /**< Working-Counter bei Empfang (wird
-                                   vom Master gesetzt) */
-  unsigned char data[EC_FRAME_SIZE]; /**< Kommandodaten */
-}
-ec_command_t;
-
-/*****************************************************************************/
-
-void ec_command_read(ec_command_t *, unsigned short, unsigned short,
-                     unsigned int);
-void ec_command_write(ec_command_t *, unsigned short, unsigned short,
-                      unsigned int, const unsigned char *);
-void ec_command_position_read(ec_command_t *, short, unsigned short,
-                              unsigned int);
-void ec_command_position_write(ec_command_t *, short, unsigned short,
-                               unsigned int, const unsigned char *);
-void ec_command_broadcast_read(ec_command_t *, unsigned short, unsigned int);
-void ec_command_broadcast_write(ec_command_t *, unsigned short, unsigned int,
-                                const unsigned char *);
-void ec_command_logical_read_write(ec_command_t *, unsigned int, unsigned int,
-                                   unsigned char *);
-
-/*****************************************************************************/
-
-#endif
--- a/master/device.c	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/device.c	Thu Feb 23 09:58:50 2006 +0000
@@ -29,32 +29,22 @@
 
 int ec_device_init(ec_device_t *ecd)
 {
-  ecd->dev = NULL;
-  ecd->open = 0;
-  ecd->tx_time = 0;
-  ecd->rx_time = 0;
-  ecd->tx_intr_cnt = 0;
-  ecd->rx_intr_cnt = 0;
-  ecd->intr_cnt = 0;
-  ecd->state = EC_DEVICE_STATE_READY;
-  ecd->rx_data_length = 0;
-  ecd->isr = NULL;
-  ecd->module = NULL;
-  ecd->error_reported = 0;
-
-  if ((ecd->tx_skb = dev_alloc_skb(EC_FRAME_SIZE)) == NULL) {
-    printk(KERN_ERR "EtherCAT: Could not allocate device tx socket buffer!\n");
-    return -1;
-  }
-
-  if ((ecd->rx_skb = dev_alloc_skb(EC_FRAME_SIZE)) == NULL) {
-    dev_kfree_skb(ecd->tx_skb);
-    ecd->tx_skb = NULL;
-    printk(KERN_ERR "EtherCAT: Could not allocate device rx socket buffer!\n");
-    return -1;
-  }
-
-  return 0;
+    ecd->dev = NULL;
+    ecd->open = 0;
+    ecd->tx_time = 0;
+    ecd->rx_time = 0;
+    ecd->state = EC_DEVICE_STATE_READY;
+    ecd->rx_data_length = 0;
+    ecd->isr = NULL;
+    ecd->module = NULL;
+    ecd->error_reported = 0;
+
+    if ((ecd->tx_skb = dev_alloc_skb(ETH_HLEN + EC_MAX_FRAME_SIZE)) == NULL) {
+        printk(KERN_ERR "EtherCAT: Error allocating device socket buffer!\n");
+        return -1;
+    }
+
+    return 0;
 }
 
 /*****************************************************************************/
@@ -70,19 +60,14 @@
 
 void ec_device_clear(ec_device_t *ecd)
 {
-  if (ecd->open) ec_device_close(ecd);
-
-  ecd->dev = NULL;
-
-  if (ecd->tx_skb) {
-    dev_kfree_skb(ecd->tx_skb);
-    ecd->tx_skb = NULL;
-  }
-
-  if (ecd->rx_skb) {
-    dev_kfree_skb(ecd->rx_skb);
-    ecd->rx_skb = NULL;
-  }
+    if (ecd->open) ec_device_close(ecd);
+
+    ecd->dev = NULL;
+
+    if (ecd->tx_skb) {
+        dev_kfree_skb(ecd->tx_skb);
+        ecd->tx_skb = NULL;
+    }
 }
 
 /*****************************************************************************/
@@ -102,34 +87,32 @@
 
 int ec_device_open(ec_device_t *ecd)
 {
-  unsigned int i;
-
-  if (!ecd) {
-    printk(KERN_ERR "EtherCAT: Trying to open a NULL device!\n");
-    return -1;
-  }
-
-  if (!ecd->dev) {
-    printk(KERN_ERR "EtherCAT: No net_device to open!\n");
-    return -1;
-  }
-
-  if (ecd->open) {
-    printk(KERN_WARNING "EtherCAT: Device already opened!\n");
-  }
-  else {
-    // Device could have received frames before
-    for (i = 0; i < 4; i++) ec_device_call_isr(ecd);
-
-    // Reset old device state
-    ecd->state = EC_DEVICE_STATE_READY;
-    ecd->tx_intr_cnt = 0;
-    ecd->rx_intr_cnt = 0;
-
-    if (ecd->dev->open(ecd->dev) == 0) ecd->open = 1;
-  }
-
-  return ecd->open ? 0 : -1;
+    unsigned int i;
+
+    if (!ecd) {
+        printk(KERN_ERR "EtherCAT: Trying to open a NULL device!\n");
+        return -1;
+    }
+
+    if (!ecd->dev) {
+        printk(KERN_ERR "EtherCAT: No net_device to open!\n");
+        return -1;
+    }
+
+    if (ecd->open) {
+        printk(KERN_WARNING "EtherCAT: Device already opened!\n");
+    }
+    else {
+        // Device could have received frames before
+        for (i = 0; i < 4; i++) ec_device_call_isr(ecd);
+
+        // Reset old device state
+        ecd->state = EC_DEVICE_STATE_READY;
+
+        if (ecd->dev->open(ecd->dev) == 0) ecd->open = 1;
+    }
+
+    return ecd->open ? 0 : -1;
 }
 
 /*****************************************************************************/
@@ -140,27 +123,42 @@
    @param ecd EtherCAT-Gerät
 
    @return 0 bei Erfolg, < 0: Kein Gerät zum Schliessen oder
-           Schliessen fehlgeschlagen.
+   Schliessen fehlgeschlagen.
 */
 
 int ec_device_close(ec_device_t *ecd)
 {
-  if (!ecd->dev) {
-    printk(KERN_ERR "EtherCAT: No device to close!\n");
-    return -1;
-  }
-
-  if (!ecd->open) {
-    printk(KERN_WARNING "EtherCAT: Device already closed!\n");
-  }
-  else {
-    printk(KERN_INFO "EtherCAT: Stopping device (txcnt: %u, rxcnt: %u)\n",
-           (unsigned int) ecd->tx_intr_cnt, (unsigned int) ecd->rx_intr_cnt);
-
-    if (ecd->dev->stop(ecd->dev) == 0) ecd->open = 0;
-  }
-
-  return !ecd->open ? 0 : -1;
+    if (!ecd->dev) {
+        printk(KERN_ERR "EtherCAT: No device to close!\n");
+        return -1;
+    }
+
+    if (!ecd->open) {
+        printk(KERN_WARNING "EtherCAT: Device already closed!\n");
+    }
+    else {
+        if (ecd->dev->stop(ecd->dev) == 0) ecd->open = 0;
+    }
+
+    return !ecd->open ? 0 : -1;
+}
+
+/*****************************************************************************/
+
+/**
+   Bereitet den geräteinternen Socket-Buffer auf den Versand vor.
+
+   \return Zeiger auf den Speicher, in den die Frame-Daten sollen.
+*/
+
+uint8_t *ec_device_prepare(ec_device_t *ecd /**< EtherCAT-Gerät */)
+{
+    // Clear transmit socket buffer and reserve space for Ethernet-II header
+    skb_trim(ecd->tx_skb, 0);
+    skb_reserve(ecd->tx_skb, ETH_HLEN);
+
+    // Erstmal Speicher für maximal langen Frame reservieren
+    return skb_put(ecd->tx_skb, EC_MAX_FRAME_SIZE);
 }
 
 /*****************************************************************************/
@@ -172,115 +170,72 @@
    Buffer, fügt den Ethernat-II-Header hinzu und ruft die
    start_xmit()-Funktion der Netzwerkkarte auf.
 
-   @param ecd EtherCAT-Gerät
-   @param data Zeiger auf die zu sendenden Daten
-   @param length Länge der zu sendenden Daten
-
-   @return 0 bei Erfolg, < 0: Vorheriger Rahmen noch
+   \return 0 bei Erfolg, < 0: Vorheriger Rahmen noch
    nicht empfangen, oder kein Speicher mehr vorhanden
 */
 
-int ec_device_send(ec_device_t *ecd, unsigned char *data, unsigned int length)
-{
-  unsigned char *frame_data;
-  struct ethhdr *eth;
-
-  if (unlikely(ecd->state == EC_DEVICE_STATE_SENT)) {
-    printk(KERN_WARNING "EtherCAT: Warning - Trying to send frame while last "
-           " was not received!\n");
-  }
-
-  // Clear transmit socket buffer and reserve
-  // space for Ethernet-II header
-  skb_trim(ecd->tx_skb, 0);
-  skb_reserve(ecd->tx_skb, ETH_HLEN);
-
-  // Copy data to socket buffer
-  frame_data = skb_put(ecd->tx_skb, length);
-  memcpy(frame_data, data, length);
-
-  // Add Ethernet-II-Header
-  if (unlikely((eth = (struct ethhdr *)
-                skb_push(ecd->tx_skb, ETH_HLEN)) == NULL)) {
-    printk(KERN_ERR "EtherCAT: device_send -"
-           " Could not allocate Ethernet-II header!\n");
-    return -1;
-  }
-
-  // Protocol type
-  eth->h_proto = htons(0x88A4);
-  // Hardware address
-  memcpy(eth->h_source, ecd->dev->dev_addr, ecd->dev->addr_len);
-  // Broadcast address
-  memset(eth->h_dest, 0xFF, ecd->dev->addr_len);
-
-  rdtscl(ecd->tx_time); // Get CPU cycles
-
-  // Start sending of frame
-  ecd->state = EC_DEVICE_STATE_SENT;
-  ecd->dev->hard_start_xmit(ecd->tx_skb, ecd->dev);
-
-  return 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Holt einen empfangenen Rahmen von der Netzwerkkarte.
-
-   Zuerst wird geprüft, ob überhaupt ein Rahmen empfangen
-   wurde. Wenn ja, wird dieser in den angegebenen
-   Speicherbereich kopiert.
-
-   @param ecd EtherCAT-Gerät
-   @param data Zeiger auf den Speicherbereich, in den die
-               empfangenen Daten kopiert werden sollen
+void ec_device_send(ec_device_t *ecd, /**< EtherCAT-Gerät */
+                    unsigned int length /**< Länge der zu sendenden Daten */
+                    )
+{
+    struct ethhdr *eth;
+
+    // Framegroesse auf (jetzt bekannte) Laenge abschneiden
+    skb_trim(ecd->tx_skb, length);
+
+    // Ethernet-II-Header hinzufuegen
+    eth = (struct ethhdr *) skb_push(ecd->tx_skb, ETH_HLEN);
+    eth->h_proto = htons(0x88A4);
+    memcpy(eth->h_source, ecd->dev->dev_addr, ecd->dev->addr_len);
+    memset(eth->h_dest, 0xFF, ecd->dev->addr_len);
+
+    ecd->state = EC_DEVICE_STATE_SENT;
+    ecd->rx_data_length = 0;
+
+    // Senden einleiten
+    rdtscl(ecd->tx_time); // Get CPU cycles
+    ecd->dev->hard_start_xmit(ecd->tx_skb, ecd->dev);
+}
+
+/*****************************************************************************/
+
+/**
+   Gibt die Anzahl der empfangenen Bytes zurück.
+
+   \return Empfangene Bytes, oder 0, wenn kein Frame empfangen wurde.
+*/
+
+unsigned int ec_device_received(const ec_device_t *ecd)
+{
+    return ecd->rx_data_length;
+}
+
+/*****************************************************************************/
+
+/**
+   Gibt die empfangenen Daten zurück.
+
+   \return Adresse auf empfangene Daten.
+*/
+
+uint8_t *ec_device_data(ec_device_t *ecd)
+{
+    return ecd->rx_data;
+}
+
+/*****************************************************************************/
+
+/**
+   Ruft die Interrupt-Routine der Netzwerkkarte auf.
+
+   @param ecd EtherCAT-Gerät
 
    @return Anzahl der kopierten Bytes bei Erfolg, sonst < 0
 */
 
-int ec_device_receive(ec_device_t *ecd, unsigned char *data)
-{
-  if (unlikely(ecd->state != EC_DEVICE_STATE_RECEIVED)) {
-    if (likely(ecd->error_reported)) {
-      printk(KERN_ERR "EtherCAT: receive - Nothing received!\n");
-      ecd->error_reported = 1;
-    }
-    return -1;
-  }
-
-  if (unlikely(ecd->rx_data_length > EC_FRAME_SIZE)) {
-    if (likely(ecd->error_reported)) {
-      printk(KERN_ERR "EtherCAT: receive - "
-             " Reveived frame is too long (%i Bytes)!\n",
-             ecd->rx_data_length);
-      ecd->error_reported = 1;
-    }
-    return -1;
-  }
-
-  if (unlikely(ecd->error_reported)) {
-    ecd->error_reported = 0;
-  }
-
-  memcpy(data, ecd->rx_data, ecd->rx_data_length);
-
-  return ecd->rx_data_length;
-}
-
-/*****************************************************************************/
-
-/**
-   Ruft die Interrupt-Routine der Netzwerkkarte auf.
-
-   @param ecd EtherCAT-Gerät
-
-   @return Anzahl der kopierten Bytes bei Erfolg, sonst < 0
-*/
-
 void ec_device_call_isr(ec_device_t *ecd)
 {
-  if (likely(ecd->isr)) ecd->isr(0, ecd->dev, NULL);
+    if (likely(ecd->isr)) ecd->isr(0, ecd->dev, NULL);
 }
 
 /*****************************************************************************/
@@ -291,41 +246,33 @@
    @param ecd EtherCAT-Gerät
 */
 
-void ec_device_debug(ec_device_t *ecd)
-{
-  printk(KERN_DEBUG "---EtherCAT device information begin---\n");
-
-  if (ecd)
-  {
-    printk(KERN_DEBUG "Assigned net_device: %X\n",
-           (unsigned) ecd->dev);
-    printk(KERN_DEBUG "Transmit socket buffer: %X\n",
-           (unsigned) ecd->tx_skb);
-    printk(KERN_DEBUG "Receive socket buffer: %X\n",
-           (unsigned) ecd->rx_skb);
-    printk(KERN_DEBUG "Time of last transmission: %u\n",
-           (unsigned) ecd->tx_time);
-    printk(KERN_DEBUG "Time of last receive: %u\n",
-           (unsigned) ecd->rx_time);
-    printk(KERN_DEBUG "Number of transmit interrupts: %u\n",
-           (unsigned) ecd->tx_intr_cnt);
-    printk(KERN_DEBUG "Number of receive interrupts: %u\n",
-           (unsigned) ecd->rx_intr_cnt);
-    printk(KERN_DEBUG "Total Number of interrupts: %u\n",
-           (unsigned) ecd->intr_cnt);
-    printk(KERN_DEBUG "Actual device state: %i\n",
-           (int) ecd->state);
-    printk(KERN_DEBUG "Receive buffer: %X\n",
-           (unsigned) ecd->rx_data);
-    printk(KERN_DEBUG "Receive buffer fill state: %u/%u\n",
-           (unsigned) ecd->rx_data_length, EC_FRAME_SIZE);
-  }
-  else
-  {
-    printk(KERN_DEBUG "Device is NULL!\n");
-  }
-
-  printk(KERN_DEBUG "---EtherCAT device information end---\n");
+void ec_device_print(ec_device_t *ecd)
+{
+    printk(KERN_DEBUG "---EtherCAT device information begin---\n");
+
+    if (ecd)
+    {
+        printk(KERN_DEBUG "Assigned net_device: %X\n",
+               (unsigned) ecd->dev);
+        printk(KERN_DEBUG "Transmit socket buffer: %X\n",
+               (unsigned) ecd->tx_skb);
+        printk(KERN_DEBUG "Time of last transmission: %u\n",
+               (unsigned) ecd->tx_time);
+        printk(KERN_DEBUG "Time of last receive: %u\n",
+               (unsigned) ecd->rx_time);
+        printk(KERN_DEBUG "Actual device state: %i\n",
+               (int) ecd->state);
+        printk(KERN_DEBUG "Receive buffer: %X\n",
+               (unsigned) ecd->rx_data);
+        printk(KERN_DEBUG "Receive buffer fill state: %u/%u\n",
+               (unsigned) ecd->rx_data_length, EC_MAX_FRAME_SIZE);
+    }
+    else
+    {
+        printk(KERN_DEBUG "Device is NULL!\n");
+    }
+
+    printk(KERN_DEBUG "---EtherCAT device information end---\n");
 }
 
 /******************************************************************************
@@ -336,36 +283,24 @@
 
 void EtherCAT_dev_state(ec_device_t *ecd, ec_device_state_t state)
 {
-  if (state == EC_DEVICE_STATE_TIMEOUT && ecd->state != EC_DEVICE_STATE_SENT) {
-    printk(KERN_WARNING "EtherCAT: Wrong status at timeout: %i\n", ecd->state);
-  }
-
-  ecd->state = state;
+    ecd->state = state;
 }
 
 /*****************************************************************************/
 
 int EtherCAT_dev_is_ec(ec_device_t *ecd, struct net_device *dev)
 {
-  return ecd && ecd->dev == dev;
-}
-
-/*****************************************************************************/
-
-int EtherCAT_dev_receive(ec_device_t *ecd, void *data, unsigned int size)
-{
-  if (ecd->state != EC_DEVICE_STATE_SENT)
-  {
-    printk(KERN_WARNING "EtherCAT: Received frame while not in SENT state!\n");
-    return -1;
-  }
-
-  // Copy received data to ethercat-device buffer, skip Ethernet-II header
-  memcpy(ecd->rx_data, data, size);
-  ecd->rx_data_length = size;
-  ecd->state = EC_DEVICE_STATE_RECEIVED;
-
-  return 0;
+    return ecd && ecd->dev == dev;
+}
+
+/*****************************************************************************/
+
+void EtherCAT_dev_receive(ec_device_t *ecd, void *data, unsigned int size)
+{
+    // Copy received data to ethercat-device buffer
+    memcpy(ecd->rx_data, data, size);
+    ecd->rx_data_length = size;
+    ecd->state = EC_DEVICE_STATE_RECEIVED;
 }
 
 /*****************************************************************************/
@@ -378,6 +313,6 @@
 
 /* Emacs-Konfiguration
 ;;; Local Variables: ***
-;;; c-basic-offset:2 ***
+;;; c-basic-offset:4 ***
 ;;; End: ***
 */
--- a/master/device.h	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/device.h	Thu Feb 23 09:58:50 2006 +0000
@@ -28,26 +28,19 @@
 
 struct ec_device
 {
-  struct net_device *dev;    /**< Zeiger auf das reservierte net_device */
-  unsigned int open;         /**< Das net_device ist geoeffnet. */
-  struct sk_buff *tx_skb;    /**< Zeiger auf Transmit-Socketbuffer */
-  struct sk_buff *rx_skb;    /**< Zeiger auf Receive-Socketbuffer */
-  unsigned long tx_time;     /**< Zeit des letzten Sendens */
-  unsigned long rx_time;     /**< Zeit des letzten Empfangs */
-  unsigned long tx_intr_cnt; /**< Anzahl Tx-Interrupts */
-  unsigned long rx_intr_cnt; /**< Anzahl Rx-Interrupts */
-  unsigned long intr_cnt;    /**< Anzahl Interrupts */
-  volatile ec_device_state_t state; /**< Gesendet, Empfangen,
-                                       Timeout, etc. */
-  unsigned char rx_data[EC_FRAME_SIZE]; /**< Puffer für
-                                           empfangene Rahmen */
-  volatile unsigned int rx_data_length; /**< Länge des zuletzt
-                                           empfangenen Rahmens */
-  irqreturn_t (*isr)(int, void *, struct pt_regs *); /**< Adresse der ISR */
-  struct module *module; /**< Zeiger auf das Modul, das das Gerät zur
-                            Verfügung stellt. */
-  int error_reported; /**< Zeigt an, ob ein Fehler im zyklischen Code
-                         bereits gemeldet wurde. */
+    struct net_device *dev; /**< Zeiger auf das reservierte net_device */
+    unsigned int open;      /**< Das net_device ist geoeffnet. */
+    struct sk_buff *tx_skb; /**< Zeiger auf Transmit-Socketbuffer */
+    unsigned long tx_time;  /**< Zeit des letzten Sendens */
+    unsigned long rx_time;  /**< Zeit des letzten Empfangs */
+    volatile ec_device_state_t state; /**< Zustand des Gerätes */
+    uint8_t rx_data[EC_MAX_FRAME_SIZE]; /**< Speicher für empfangene Rahmen */
+    volatile unsigned int rx_data_length; /**< Länge des empfangenen Rahmens */
+    irqreturn_t (*isr)(int, void *, struct pt_regs *); /**< Adresse der ISR */
+    struct module *module; /**< Zeiger auf das Modul, das das Gerät zur
+                              Verfügung stellt. */
+    int error_reported; /**< Zeigt an, ob ein Fehler im zyklischen Code
+                           bereits gemeldet wurde. */
 };
 
 /*****************************************************************************/
@@ -57,9 +50,17 @@
 int ec_device_open(ec_device_t *);
 int ec_device_close(ec_device_t *);
 void ec_device_call_isr(ec_device_t *);
-int ec_device_send(ec_device_t *, unsigned char *, unsigned int);
-int ec_device_receive(ec_device_t *, unsigned char *);
+uint8_t *ec_device_prepare(ec_device_t *);
+void ec_device_send(ec_device_t *, unsigned int);
+unsigned int ec_device_received(const ec_device_t *);
+uint8_t *ec_device_data(ec_device_t *);
 
 /*****************************************************************************/
 
 #endif
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:4 ***
+;;; End: ***
+*/
--- a/master/domain.c	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/domain.c	Thu Feb 23 09:58:50 2006 +0000
@@ -8,33 +8,349 @@
  *
  *****************************************************************************/
 
-#include <linux/module.h>
-
 #include "globals.h"
 #include "domain.h"
+#include "master.h"
 
 /*****************************************************************************/
 
 /**
    Konstruktor einer EtherCAT-Domäne.
-
-   @param dom Zeiger auf die zu initialisierende Domäne
-*/
-
-void ec_domain_init(ec_domain_t *dom)
-{
-  dom->number = -1;
-  dom->data_size = 0;
-  dom->logical_offset = 0;
-  dom->response_count = 0xFFFFFFFF;
-
-  memset(dom->data, 0x00, EC_FRAME_SIZE);
-}
+*/
+
+void ec_domain_init(ec_domain_t *domain, /**< Domäne */
+                    ec_master_t *master, /**< Zugehöriger Master */
+                    ec_domain_mode_t mode, /**< Synchron/Asynchron */
+                    unsigned int timeout_us /**< Timeout in Mikrosekunden */
+                    )
+{
+    domain->master = master;
+    domain->mode = mode;
+    domain->timeout_us = timeout_us;
+
+    domain->data = NULL;
+    domain->data_size = 0;
+    domain->base_address = 0;
+    domain->response_count = 0xFFFFFFFF;
+
+    INIT_LIST_HEAD(&domain->field_regs);
+}
+
+/*****************************************************************************/
+
+/**
+   Destruktor einer EtherCAT-Domäne.
+*/
+
+void ec_domain_clear(ec_domain_t *domain /**< Domäne */)
+{
+    ec_field_reg_t *field_reg, *next;
+
+    if (domain->data) {
+        kfree(domain->data);
+        domain->data = NULL;
+    }
+
+    // Liste der registrierten Datenfelder löschen
+    list_for_each_entry_safe(field_reg, next, &domain->field_regs, list) {
+        kfree(field_reg);
+    }
+}
+
+/*****************************************************************************/
+
+/**
+   Registriert ein Feld in einer Domäne.
+
+   \returns 0 bei Erfolg, < 0 bei Fehler
+*/
+
+int ec_domain_reg_field(ec_domain_t *domain, /**< Domäne */
+                        ec_slave_t *slave, /**< Slave */
+                        const ec_sync_t *sync, /**< Sync-Manager */
+                        uint32_t field_offset, /**< Datenfeld-Offset */
+                        void **data_ptr /**< Adresse des Prozessdatenzeigers */
+                        )
+{
+    ec_field_reg_t *field_reg;
+
+    if (!(field_reg = (ec_field_reg_t *) kmalloc(sizeof(ec_field_reg_t),
+                                                 GFP_KERNEL))) {
+        printk(KERN_ERR "EtherCAT: Failed to allocate field registration.\n");
+        return -1;
+    }
+
+    if (ec_slave_set_fmmu(slave, domain, sync)) {
+        printk(KERN_ERR "EtherCAT: FMMU configuration failed.\n");
+        kfree(field_reg);
+        return -1;
+    }
+
+    field_reg->slave = slave;
+    field_reg->sync = sync;
+    field_reg->field_offset = field_offset;
+    field_reg->data_ptr = data_ptr;
+
+    list_add_tail(&field_reg->list, &domain->field_regs);
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+    \returns 0 bei Erfolg, < 0 bei Fehler
+*/
+
+int ec_domain_alloc(ec_domain_t *domain, /**< Domäne */
+                    uint32_t base_address /**< Logische Basisadresse */
+                    )
+{
+    ec_field_reg_t *field_reg, *next;
+    ec_slave_t *slave;
+    ec_fmmu_t *fmmu;
+    unsigned int i, j, found, data_offset;
+
+    if (domain->data) {
+        printk(KERN_ERR "EtherCAT: Domain already allocated!\n");
+        return -1;
+    }
+
+    domain->base_address = base_address;
+
+    // Größe der Prozessdaten berechnen
+    // und logische Adressen der FMMUs setzen
+    domain->data_size = 0;
+    for (i = 0; i < domain->master->slave_count; i++) {
+        slave = &domain->master->slaves[i];
+        for (j = 0; j < slave->fmmu_count; j++) {
+            fmmu = &slave->fmmus[j];
+            if (fmmu->domain == domain) {
+                fmmu->logical_start_address = base_address + domain->data_size;
+                domain->data_size += fmmu->sync->size;
+            }
+        }
+    }
+
+    if (!domain->data_size) {
+        printk(KERN_WARNING "EtherCAT: Domain 0x%08X contains no data!\n",
+               (u32) domain);
+    }
+    else {
+        // Prozessdaten allozieren
+        if (!(domain->data = kmalloc(domain->data_size, GFP_KERNEL))) {
+            printk(KERN_ERR "EtherCAT: Failed to allocate domain data!\n");
+            return -1;
+        }
+
+        // Prozessdaten mit Nullen vorbelegen
+        memset(domain->data, 0x00, domain->data_size);
+
+        // Alle Prozessdatenzeiger setzen
+        list_for_each_entry(field_reg, &domain->field_regs, list) {
+            found = 0;
+            for (i = 0; i < field_reg->slave->fmmu_count; i++) {
+                fmmu = &field_reg->slave->fmmus[i];
+                if (fmmu->domain == domain && fmmu->sync == field_reg->sync) {
+                    data_offset = fmmu->logical_start_address - base_address
+                        + field_reg->field_offset;
+                    *field_reg->data_ptr = domain->data + data_offset;
+                    found = 1;
+                    break;
+                }
+            }
+
+            if (!found) { // Sollte nie passieren
+                printk(KERN_ERR "EtherCAT: FMMU not found. Please report!\n");
+                return -1;
+            }
+        }
+    }
+
+    // Registrierungsliste wird jetzt nicht mehr gebraucht.
+    list_for_each_entry_safe(field_reg, next, &domain->field_regs, list) {
+        kfree(field_reg);
+    }
+    INIT_LIST_HEAD(&domain->field_regs); // wichtig!
+
+    return 0;
+}
+
+/******************************************************************************
+ *
+ * Echtzeitschnittstelle
+ *
+ *****************************************************************************/
+
+/**
+   Registriert einer Domäne ein Datenfeld hinzu.
+
+   \return Zeiger auf den Slave bei Erfolg, sonst NULL
+*/
+
+ec_slave_t *EtherCAT_rt_register_slave_field(
+    ec_domain_t *domain, /**< Domäne */
+    const char *address, /**< ASCII-Addresse des Slaves, siehe ec_address() */
+    const char *vendor_name, /**< Herstellername */
+    const char *product_name, /**< Produktname */
+    void **data_ptr, /**< Adresse des Zeigers auf die Prozessdaten */
+    ec_field_type_t field_type, /**< Typ des Datenfeldes */
+    unsigned int field_index, /**< Gibt an, ab welchem Feld mit Typ
+                                 \a field_type gezählt werden soll. */
+    unsigned int field_count /**< Anzahl Felder des selben Typs */
+    )
+{
+    ec_slave_t *slave;
+    const ec_slave_type_t *type;
+    ec_master_t *master;
+    const ec_sync_t *sync;
+    const ec_field_t *field;
+    unsigned int field_idx, found, i, j;
+    uint32_t field_offset;
+
+    if (!field_count) {
+        printk(KERN_ERR "EtherCAT: field_count may not be 0!\n");
+        return NULL;
+    }
+
+    master = domain->master;
+
+    // Adresse übersetzen
+    if ((slave = ec_address(master, address)) == NULL) return NULL;
+
+    if (!(type = slave->type)) {
+        printk(KERN_ERR "EtherCAT: Slave \"%s\" (position %i) has unknown"
+               " type!\n", address, slave->ring_position);
+        return NULL;
+    }
+
+    if (strcmp(vendor_name, type->vendor_name) ||
+        strcmp(product_name, type->product_name)) {
+        printk(KERN_ERR "EtherCAT: Invalid slave type at position %i -"
+               " Requested: \"%s %s\", found: \"%s %s\".\n",
+               slave->ring_position, vendor_name, product_name,
+               type->vendor_name, type->product_name);
+        return NULL;
+    }
+
+    field_idx = 0;
+    found = 0;
+    for (i = 0; type->sync_managers[i] && !found; i++) {
+        sync = type->sync_managers[i];
+        field_offset = 0;
+        for (j = 0; sync->fields[j]; j++) {
+            field = sync->fields[j];
+            if (field->type == field_type) {
+                if (field_idx == field_index) {
+                    ec_domain_reg_field(domain, slave, sync, field_offset,
+                                        data_ptr++);
+                    if (!(--field_count)) return slave;
+                }
+                field_idx++;
+            }
+            field_offset += field->size;
+        }
+    }
+
+    printk(KERN_ERR "EtherCAT: Slave %i (\"%s %s\") has less than %i fields of"
+           " type %i, starting at %i!\n", slave->ring_position,
+           vendor_name, product_name, field_count, field_type, field_index);
+    return NULL;
+}
+
+/*****************************************************************************/
+
+/**
+   Sendet und empfängt Prozessdaten der angegebenen Domäne
+
+   \return 0 bei Erfolg, sonst < 0
+*/
+
+int EtherCAT_rt_domain_xio(ec_domain_t *domain /**< Domäne */)
+{
+    unsigned int offset, size, working_counter_sum;
+    unsigned long start_ticks, end_ticks, timeout_ticks;
+    ec_master_t *master;
+    ec_frame_t *frame;
+
+    master = domain->master;
+    frame = &domain->frame;
+    working_counter_sum = 0;
+
+    ec_output_lost_frames(master); // Evtl. verlorene Frames ausgeben
+
+    rdtscl(start_ticks); // Sendezeit nehmen
+    timeout_ticks = domain->timeout_us * cpu_khz / 1000;
+
+    offset = 0;
+    while (offset < domain->data_size)
+    {
+        size = domain->data_size - offset;
+        if (size > EC_MAX_DATA_SIZE) size = EC_MAX_DATA_SIZE;
+
+        ec_frame_init_lrw(frame, master, domain->base_address + offset, size,
+                          domain->data + offset);
+
+        if (unlikely(ec_frame_send(frame) < 0)) {
+            printk(KERN_ERR "EtherCAT: Could not send process data"
+                   " command!\n");
+            return -1;
+        }
+
+        // Warten
+        do {
+            ec_device_call_isr(&master->device);
+            rdtscl(end_ticks); // Empfangszeit nehmen
+        }
+        while (unlikely(master->device.state == EC_DEVICE_STATE_SENT
+                        && end_ticks - start_ticks < timeout_ticks));
+
+        master->bus_time = (end_ticks - start_ticks) * 1000 / cpu_khz;
+
+        if (unlikely(end_ticks - start_ticks >= timeout_ticks)) {
+            master->device.state = EC_DEVICE_STATE_READY;
+            master->frames_lost++;
+            ec_output_lost_frames(master);
+            return -1;
+        }
+
+        if (unlikely(ec_frame_receive(frame) < 0)) {
+            printk(KERN_ERR "EtherCAT: Receive error!\n");
+            return -1;
+        }
+
+        if (unlikely(frame->state != ec_frame_received)) {
+            printk(KERN_WARNING "EtherCAT: Process data command not"
+                   " received!\n");
+            return -1;
+        }
+
+        working_counter_sum += frame->working_counter;
+
+        // Daten vom Rahmen in den Prozessdatenspeicher kopieren
+        memcpy(domain->data + offset, frame->data, size);
+
+        offset += size;
+    }
+
+    if (working_counter_sum != domain->response_count) {
+        domain->response_count = working_counter_sum;
+        printk(KERN_INFO "EtherCAT: Domain %08X state change - %i slaves"
+               " responding.\n", (unsigned int) domain, working_counter_sum);
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+EXPORT_SYMBOL(EtherCAT_rt_register_slave_field);
+EXPORT_SYMBOL(EtherCAT_rt_domain_xio);
 
 /*****************************************************************************/
 
 /* Emacs-Konfiguration
 ;;; Local Variables: ***
-;;; c-basic-offset:2 ***
+;;; c-basic-offset:4 ***
 ;;; End: ***
 */
--- a/master/domain.h	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/domain.h	Thu Feb 23 09:58:50 2006 +0000
@@ -11,9 +11,27 @@
 #ifndef _EC_DOMAIN_H_
 #define _EC_DOMAIN_H_
 
+#include <linux/list.h>
+
 #include "globals.h"
 #include "slave.h"
-#include "command.h"
+#include "frame.h"
+
+/*****************************************************************************/
+
+/**
+   Datenfeld-Konfiguration.
+*/
+
+typedef struct
+{
+    struct list_head list;
+    ec_slave_t *slave;
+    const ec_sync_t *sync;
+    uint32_t field_offset;
+    void **data_ptr;
+}
+ec_field_reg_t;
 
 /*****************************************************************************/
 
@@ -24,28 +42,37 @@
    Menge von Slaves.
 */
 
-typedef struct ec_domain
+struct ec_domain
 {
-  int number; /*<< Domänen-Identifikation */
-  ec_command_t command; /**< Kommando zum Senden und Empfangen der
-                           Prozessdaten */
-  unsigned char data[EC_FRAME_SIZE]; /**< Prozessdaten-Array */
-  unsigned int data_size; /**< Größe der Prozessdaten */
-  unsigned int logical_offset; /**< Logische Basisaddresse */
-  unsigned int response_count; /**< Anzahl antwortender Slaves */
-}
-ec_domain_t;
+    ec_master_t *master; /**< EtherCAT-Master, zu der die Domäne gehört. */
+
+    unsigned char *data; /**< Prozessdaten */
+    unsigned int data_size; /**< Größe der Prozessdaten */
+
+    ec_frame_t frame; /**< EtherCAT-Frame für die Prozessdaten */
+
+    ec_domain_mode_t mode;
+    unsigned int timeout_us; /**< Timeout in Mikrosekunden. */
+    unsigned int base_address; /**< Logische Basisaddresse der Domain */
+    unsigned int response_count; /**< Anzahl antwortender Slaves */
+
+    struct list_head field_regs; /**< Liste der Datenfeldregistrierungen */
+};
 
 /*****************************************************************************/
 
-void ec_domain_init(ec_domain_t *);
+void ec_domain_init(ec_domain_t *, ec_master_t *, ec_domain_mode_t,
+                    unsigned int);
+void ec_domain_clear(ec_domain_t *);
+
+int ec_domain_alloc(ec_domain_t *, uint32_t);
 
 /*****************************************************************************/
 
 #endif
 
 /* Emacs-Konfiguration
-;;; Local Variables: ***
-;;; c-basic-offset:2 ***
+   ;;; Local Variables: ***
+   ;;; c-basic-offset:4 ***
 ;;; End: ***
 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/frame.c	Thu Feb 23 09:58:50 2006 +0000
@@ -0,0 +1,494 @@
+/******************************************************************************
+ *
+ *  f r a m e . c
+ *
+ *  Methoden für einen EtherCAT-Frame.
+ *
+ *  $Id$
+ *
+ *****************************************************************************/
+
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include "frame.h"
+#include "master.h"
+
+/*****************************************************************************/
+
+#define EC_FUNC_HEADER \
+    frame->master = master; \
+    frame->state = ec_frame_ready; \
+    frame->index = 0; \
+    frame->working_counter = 0;
+
+#define EC_FUNC_WRITE_FOOTER \
+    frame->data_length = length; \
+    memcpy(frame->data, data, length);
+
+#define EC_FUNC_READ_FOOTER \
+    frame->data_length = length;
+
+/*****************************************************************************/
+
+/**
+   Initialisiert ein EtherCAT-NPRD-Kommando.
+
+   Node-adressed physical read.
+*/
+
+void ec_frame_init_nprd(ec_frame_t *frame,
+                        /**< EtherCAT-Rahmen */
+                        ec_master_t *master,
+                        /**< EtherCAT-Master */
+                        uint16_t node_address,
+                        /**< Adresse des Knotens (Slaves) */
+                        uint16_t offset,
+                        /**< Physikalische Speicheradresse im Slave */
+                        unsigned int length
+                        /**< Länge der zu lesenden Daten */
+                        )
+{
+    if (unlikely(node_address == 0x0000))
+        printk(KERN_WARNING "EtherCAT: Warning - Using node address 0x0000!\n");
+
+    EC_FUNC_HEADER;
+
+    frame->type = ec_frame_type_nprd;
+    frame->address.physical.slave = node_address;
+    frame->address.physical.mem = offset;
+
+    EC_FUNC_READ_FOOTER;
+}
+
+/*****************************************************************************/
+
+/**
+   Initialisiert ein EtherCAT-NPWR-Kommando.
+
+   Node-adressed physical write.
+*/
+
+void ec_frame_init_npwr(ec_frame_t *frame,
+                        /**< EtherCAT-Rahmen */
+                        ec_master_t *master,
+                        /**< EtherCAT-Master */
+                        uint16_t node_address,
+                        /**< Adresse des Knotens (Slaves) */
+                        uint16_t offset,
+                        /**< Physikalische Speicheradresse im Slave */
+                        unsigned int length,
+                        /**< Länge der zu schreibenden Daten */
+                        const uint8_t *data
+                        /**< Zeiger auf Speicher mit zu schreibenden Daten */
+                        )
+{
+    if (unlikely(node_address == 0x0000))
+        printk(KERN_WARNING "EtherCAT: Warning - Using node address 0x0000!\n");
+
+    EC_FUNC_HEADER;
+
+    frame->type = ec_frame_type_npwr;
+    frame->address.physical.slave = node_address;
+    frame->address.physical.mem = offset;
+
+    EC_FUNC_WRITE_FOOTER;
+}
+
+/*****************************************************************************/
+
+/**
+   Initialisiert ein EtherCAT-APRD-Kommando.
+
+   Autoincrement physical read.
+*/
+
+void ec_frame_init_aprd(ec_frame_t *frame,
+                        /**< EtherCAT-Rahmen */
+                        ec_master_t *master,
+                        /**< EtherCAT-Master */
+                        uint16_t ring_position,
+                        /**< Position des Slaves im Bus */
+                        uint16_t offset,
+                        /**< Physikalische Speicheradresse im Slave */
+                        unsigned int length
+                        /**< Länge der zu lesenden Daten */
+                        )
+{
+    EC_FUNC_HEADER;
+
+    frame->type = ec_frame_type_aprd;
+    frame->address.physical.slave = (int16_t) ring_position * (-1);
+    frame->address.physical.mem = offset;
+
+    EC_FUNC_READ_FOOTER;
+}
+
+/*****************************************************************************/
+
+/**
+   Initialisiert ein EtherCAT-APWR-Kommando.
+
+   Autoincrement physical write.
+*/
+
+void ec_frame_init_apwr(ec_frame_t *frame,
+                        /**< EtherCAT-Rahmen */
+                        ec_master_t *master,
+                        /**< EtherCAT-Master */
+                        uint16_t ring_position,
+                        /**< Position des Slaves im Bus */
+                        uint16_t offset,
+                        /**< Physikalische Speicheradresse im Slave */
+                        unsigned int length,
+                        /**< Länge der zu schreibenden Daten */
+                        const uint8_t *data
+                        /**< Zeiger auf Speicher mit zu schreibenden Daten */
+                        )
+{
+    EC_FUNC_HEADER;
+
+    frame->type = ec_frame_type_apwr;
+    frame->address.physical.slave = (int16_t) ring_position * (-1);
+    frame->address.physical.mem = offset;
+
+    EC_FUNC_WRITE_FOOTER;
+}
+
+/*****************************************************************************/
+
+/**
+   Initialisiert ein EtherCAT-BRD-Kommando.
+
+   Broadcast read.
+*/
+
+void ec_frame_init_brd(ec_frame_t *frame,
+                       /**< EtherCAT-Rahmen */
+                       ec_master_t *master,
+                       /**< EtherCAT-Master */
+                       uint16_t offset,
+                       /**< Physikalische Speicheradresse im Slave */
+                       unsigned int length
+                       /**< Länge der zu lesenden Daten */
+                       )
+{
+    EC_FUNC_HEADER;
+
+    frame->type = ec_frame_type_brd;
+    frame->address.physical.slave = 0x0000;
+    frame->address.physical.mem = offset;
+
+    EC_FUNC_READ_FOOTER;
+}
+
+/*****************************************************************************/
+
+/**
+   Initialisiert ein EtherCAT-BWR-Kommando.
+
+   Broadcast write.
+*/
+
+void ec_frame_init_bwr(ec_frame_t *frame,
+                       /**< EtherCAT-Rahmen */
+                       ec_master_t *master,
+                       /**< EtherCAT-Master */
+                       uint16_t offset,
+                       /**< Physikalische Speicheradresse im Slave */
+                       unsigned int length,
+                       /**< Länge der zu schreibenden Daten */
+                       const uint8_t *data
+                       /**< Zeiger auf Speicher mit zu schreibenden Daten */
+                       )
+{
+    EC_FUNC_HEADER;
+
+    frame->type = ec_frame_type_bwr;
+    frame->address.physical.slave = 0x0000;
+    frame->address.physical.mem = offset;
+
+    EC_FUNC_WRITE_FOOTER;
+}
+
+/*****************************************************************************/
+
+/**
+   Initialisiert ein EtherCAT-LRW-Kommando.
+
+   Logical read write.
+*/
+
+void ec_frame_init_lrw(ec_frame_t *frame,
+                       /**< EtherCAT-Rahmen */
+                       ec_master_t *master,
+                       /**< EtherCAT-Master */
+                       uint32_t offset,
+                       /**< Logische Startadresse */
+                       unsigned int length,
+                       /**< Länge der zu lesenden/schreibenden Daten */
+                       uint8_t *data
+                       /**< Zeiger auf die Daten */
+                       )
+{
+    EC_FUNC_HEADER;
+
+    frame->type = ec_frame_type_lrw;
+    frame->address.logical = offset;
+
+    EC_FUNC_WRITE_FOOTER;
+}
+
+/*****************************************************************************/
+
+/**
+   Sendet einen einzelnen EtherCAT-Rahmen.
+
+   \return 0 bei Erfolg, sonst < 0
+*/
+
+int ec_frame_send(ec_frame_t *frame /**< Rahmen zum Senden */)
+{
+    unsigned int command_size, frame_size, i;
+    uint8_t *data;
+
+    if (unlikely(frame->master->debug_level > 0)) {
+        printk(KERN_DEBUG "EtherCAT: ec_frame_send\n");
+    }
+
+    if (unlikely(frame->state != ec_frame_ready)) {
+        printk(KERN_WARNING "EtherCAT: Frame not in \"ready\" state!\n");
+    }
+
+    command_size = frame->data_length + EC_COMMAND_HEADER_SIZE
+        + EC_COMMAND_FOOTER_SIZE;
+    frame_size = command_size + EC_FRAME_HEADER_SIZE;
+
+    if (unlikely(frame_size > EC_MAX_FRAME_SIZE)) {
+        printk(KERN_ERR "EtherCAT: Frame too long (%i)!\n", frame_size);
+        return -1;
+    }
+
+    if (frame_size < EC_MIN_FRAME_SIZE) frame_size = EC_MIN_FRAME_SIZE;
+
+    if (unlikely(frame->master->debug_level > 0)) {
+        printk(KERN_DEBUG "EtherCAT: Frame length: %i\n", frame_size);
+    }
+
+    frame->index = frame->master->command_index;
+    frame->master->command_index = (frame->master->command_index + 1) % 0x0100;
+
+    if (unlikely(frame->master->debug_level > 0)) {
+        printk(KERN_DEBUG "EtherCAT: Sending command index 0x%X\n",
+               frame->index);
+    }
+
+    frame->state = ec_frame_sent;
+
+    // Zeiger auf Socket-Buffer holen
+    data = ec_device_prepare(&frame->master->device);
+
+    // EtherCAT frame header
+    data[0] = command_size & 0xFF;
+    data[1] = ((command_size & 0x700) >> 8) | 0x10;
+    data += EC_FRAME_HEADER_SIZE;
+
+    // EtherCAT command header
+    data[0] = frame->type;
+    data[1] = frame->index;
+    data[2] = frame->address.raw[0];
+    data[3] = frame->address.raw[1];
+    data[4] = frame->address.raw[2];
+    data[5] = frame->address.raw[3];
+    data[6] = frame->data_length & 0xFF;
+    data[7] = (frame->data_length & 0x700) >> 8;
+    data[8] = 0x00;
+    data[9] = 0x00;
+    data += EC_COMMAND_HEADER_SIZE;
+
+    if (likely(frame->type == ec_frame_type_apwr // Write commands
+               || frame->type == ec_frame_type_npwr
+               || frame->type == ec_frame_type_bwr
+               || frame->type == ec_frame_type_lrw)) {
+        memcpy(data, frame->data, frame->data_length);
+    }
+    else { // Read commands
+        memset(data, 0x00, frame->data_length);
+    }
+
+    // EtherCAT command footer
+    data += frame->data_length;
+    data[0] = frame->working_counter & 0xFF;
+    data[1] = (frame->working_counter & 0xFF00) >> 8;
+    data += EC_COMMAND_FOOTER_SIZE;
+
+    // Pad with zeros
+    for (i = EC_FRAME_HEADER_SIZE + EC_COMMAND_HEADER_SIZE
+             + frame->data_length + EC_COMMAND_FOOTER_SIZE;
+         i < EC_MIN_FRAME_SIZE; i++) {
+        *data++ = 0x00;
+    }
+
+    // Send frame
+    ec_device_send(&frame->master->device, frame_size);
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Empfängt einen gesendeten Rahmen.
+
+   \return 0 bei Erfolg, sonst < 0
+*/
+
+int ec_frame_receive(ec_frame_t *frame /**< Gesendeter Rahmen */)
+{
+    unsigned int received_length, frame_length, data_length;
+    uint8_t *data;
+    uint8_t command_type, command_index;
+    ec_device_t *device;
+
+    if (unlikely(frame->state != ec_frame_sent)) {
+        printk(KERN_ERR "EtherCAT: Frame was not sent!\n");
+        return -1;
+    }
+
+    device = &frame->master->device;
+
+    if (!(received_length = ec_device_received(device))) return -1;
+
+    device->state = EC_DEVICE_STATE_READY;
+
+    if (unlikely(received_length < EC_FRAME_HEADER_SIZE)) {
+        printk(KERN_ERR "EtherCAT: Received frame with incomplete EtherCAT"
+               " frame header!\n");
+        ec_frame_print(frame);
+        return -1;
+    }
+
+    data = ec_device_data(device);
+
+    // Länge des gesamten Frames prüfen
+    frame_length = (data[0] & 0xFF) | ((data[1] & 0x07) << 8);
+
+    if (unlikely(frame_length > received_length)) {
+        printk(KERN_ERR "EtherCAT: Received corrupted frame (length does"
+               " not match)!\n");
+        ec_frame_print(frame);
+        return -1;
+    }
+
+    // Command header
+    data += EC_FRAME_HEADER_SIZE;
+    command_type = data[0];
+    command_index = data[1];
+    data_length = (data[6] & 0xFF) | ((data[7] & 0x07) << 8);
+
+    if (unlikely(EC_FRAME_HEADER_SIZE + EC_COMMAND_HEADER_SIZE
+                 + data_length + EC_COMMAND_FOOTER_SIZE > received_length)) {
+        printk(KERN_ERR "EtherCAT: Received frame with incomplete command"
+               " data!\n");
+        ec_frame_print(frame);
+        return -1;
+    }
+
+    if (unlikely(frame->type != command_type
+                 || frame->index != command_index
+                 || frame->data_length != data_length))
+    {
+        printk(KERN_WARNING "EtherCAT: WARNING - Send/Receive anomaly!\n");
+        ec_frame_print(frame);
+        ec_device_call_isr(device); // Empfangenes "vergessen"
+        return -1;
+    }
+
+    frame->state = ec_frame_received;
+
+    // Empfangene Daten in Kommandodatenspeicher kopieren
+    data += EC_COMMAND_HEADER_SIZE;
+    memcpy(frame->data, data, data_length);
+    data += data_length;
+
+    // Working-Counter setzen
+    frame->working_counter = (data[0] & 0xFF) | ((data[1] & 0xFF) << 8);
+
+    if (unlikely(frame->master->debug_level > 1)) {
+        ec_frame_print(frame);
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Sendet einen einzeln Rahmen und wartet auf dessen Empfang.
+
+   \return 0 bei Erfolg, sonst < 0
+*/
+
+int ec_frame_send_receive(ec_frame_t *frame
+                          /**< Rahmen zum Senden/Empfangen */
+                          )
+{
+    unsigned int tries_left;
+
+    if (unlikely(ec_frame_send(frame) < 0)) {
+        printk(KERN_ERR "EtherCAT: Frame sending failed!\n");
+        return -1;
+    }
+
+    tries_left = 20;
+    do
+    {
+        udelay(1);
+        ec_device_call_isr(&frame->master->device);
+        tries_left--;
+    }
+    while (unlikely(!ec_device_received(&frame->master->device)
+                    && tries_left));
+
+    if (unlikely(!tries_left)) {
+        printk(KERN_ERR "EtherCAT: Frame timeout!\n");
+        return -1;
+    }
+
+    if (unlikely(ec_frame_receive(frame) < 0)) {
+        printk(KERN_ERR "EtherCAT: Frame receiving failed!\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Gibt Frame-Inhalte zwecks Debugging aus.
+*/
+
+void ec_frame_print(const ec_frame_t *frame /**< EtherCAT-Frame */)
+{
+    unsigned int i;
+
+    printk(KERN_DEBUG "EtherCAT: Frame contents (%i Bytes):\n",
+           frame->data_length);
+
+    printk(KERN_DEBUG);
+    for (i = 0; i < frame->data_length; i++)
+    {
+        printk("%02X ", frame->data[i]);
+        if ((i + 1) % 16 == 0) printk("\n" KERN_DEBUG);
+    }
+    printk("\n");
+}
+
+/*****************************************************************************/
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:4 ***
+;;; End: ***
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/frame.h	Thu Feb 23 09:58:50 2006 +0000
@@ -0,0 +1,132 @@
+/******************************************************************************
+ *
+ *  f r a m e . h
+ *
+ *  Struktur für einen EtherCAT-Rahmen.
+ *
+ *  $Id$
+ *
+ *****************************************************************************/
+
+#ifndef _EC_FRAME_H_
+#define _EC_FRAME_H_
+
+#include "globals.h"
+#include "../include/EtherCAT_rt.h"
+
+/*****************************************************************************/
+
+#define EC_MAX_DATA_SIZE (EC_MAX_FRAME_SIZE - EC_FRAME_HEADER_SIZE \
+                                            - EC_COMMAND_HEADER_SIZE \
+                                            - EC_COMMAND_FOOTER_SIZE)
+
+/*****************************************************************************/
+
+/**
+   Status eines EtherCAT-Rahmens.
+*/
+
+typedef enum {
+  ec_frame_ready, ec_frame_sent, ec_frame_received
+}
+ec_frame_state_t;
+
+/*****************************************************************************/
+
+/**
+   EtherCAT-Rahmen-Typ
+*/
+
+typedef enum
+{
+  ec_frame_type_none = 0x00, /**< Dummy */
+  ec_frame_type_aprd = 0x01, /**< Auto-increment physical read */
+  ec_frame_type_apwr = 0x02, /**< Auto-increment physical write */
+  ec_frame_type_nprd = 0x04, /**< Node-addressed physical read */
+  ec_frame_type_npwr = 0x05, /**< Node-addressed physical write */
+  ec_frame_type_brd = 0x07,  /**< Broadcast read */
+  ec_frame_type_bwr = 0x08,  /**< Broadcast write */
+  ec_frame_type_lrw = 0x0C   /**< Logical read/write */
+}
+ec_frame_type_t;
+
+/*****************************************************************************/
+
+/**
+   EtherCAT-Adresse.
+
+   Im EtherCAT-Rahmen sind 4 Bytes für die Adresse reserviert, die je nach
+   Kommandotyp, eine andere Bedeutung haben können: Bei Autoinkrementbefehlen
+   sind die ersten zwei Bytes die (negative) Autoinkrement-Adresse, bei Knoten-
+   adressierten Befehlen entsprechen sie der Knotenadresse. Das dritte und
+   vierte Byte entspricht in diesen Fällen der physikalischen Speicheradresse
+   auf dem Slave. Bei einer logischen Adressierung entsprechen alle vier Bytes
+   der logischen Adresse.
+*/
+
+typedef union
+{
+  struct
+  {
+      uint16_t slave; /**< Adresse des Slaves */
+      uint16_t mem; /**< Physikalische Speicheradresse im Slave */
+  }
+  physical; /**< Physikalische Adresse */
+
+  uint32_t logical; /**< Logische Adresse */
+  uint8_t raw[4]; /**< Rohdaten für die Generierung des Frames */
+}
+ec_address_t;
+
+/*****************************************************************************/
+
+/**
+   EtherCAT-Frame.
+*/
+
+typedef struct
+{
+    ec_master_t *master; /**< EtherCAT-Master */
+    ec_frame_type_t type; /**< Typ des Frames (APRD, NPWR, etc) */
+    ec_address_t address; /**< Adresse des/der Empfänger */
+    unsigned int data_length; /**< Länge der zu sendenden und/oder empfangenen
+                                 Daten */
+    ec_frame_state_t state; /**< Zustand des Kommandos */
+    uint8_t index; /**< Kommando-Index, mit dem der Frame gesendet wurde
+                            (wird vom Master beim Senden gesetzt). */
+    uint16_t working_counter; /**< Working-Counter */
+    uint8_t data[EC_MAX_FRAME_SIZE]; /**< Rahmendaten */
+}
+ec_frame_t;
+
+/*****************************************************************************/
+
+void ec_frame_init_nprd(ec_frame_t *, ec_master_t *, uint16_t, uint16_t,
+                        unsigned int);
+void ec_frame_init_npwr(ec_frame_t *, ec_master_t *, uint16_t, uint16_t,
+                        unsigned int, const unsigned char *);
+void ec_frame_init_aprd(ec_frame_t *, ec_master_t *, uint16_t, uint16_t,
+                        unsigned int);
+void ec_frame_init_apwr(ec_frame_t *, ec_master_t *, uint16_t, uint16_t,
+                        unsigned int, const unsigned char *);
+void ec_frame_init_brd(ec_frame_t *, ec_master_t *, uint16_t, unsigned int);
+void ec_frame_init_bwr(ec_frame_t *, ec_master_t *, uint16_t, unsigned int,
+                       const unsigned char *);
+void ec_frame_init_lrw(ec_frame_t *, ec_master_t *, uint32_t, unsigned int,
+                       unsigned char *);
+
+int ec_frame_send(ec_frame_t *);
+int ec_frame_receive(ec_frame_t *);
+int ec_frame_send_receive(ec_frame_t *);
+
+void ec_frame_print(const ec_frame_t *);
+
+/*****************************************************************************/
+
+#endif
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:4 ***
+;;; End: ***
+*/
--- a/master/globals.h	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/globals.h	Thu Feb 23 09:58:50 2006 +0000
@@ -13,65 +13,51 @@
 
 /*****************************************************************************/
 
-/**
-   Maximale Größe eines EtherCAT-Frames
-*/
-#define EC_FRAME_SIZE 1500
+// EtherCAT-Protokoll
+#define EC_MAX_FRAME_SIZE 1500 /**< Maximale Größe eines EtherCAT-Frames ohne
+                                  Ethernet-II-Header und -Prüfsumme*/
+#define EC_MIN_FRAME_SIZE 46 /** Minimale Größe, s. o. */
+#define EC_FRAME_HEADER_SIZE 2 /**< Größe des EtherCAT-Frame-Headers */
+#define EC_COMMAND_HEADER_SIZE 10 /**< Größe eines EtherCAT-Kommando-Headers */
+#define EC_COMMAND_FOOTER_SIZE 2 /**< Größe eines EtherCAT-Kommando-Footers */
+#define EC_SYNC_SIZE 8 /**< Größe einer Sync-Manager-Konfigurationsseite */
+#define EC_FMMU_SIZE 16 /**< Größe einer FMMU-Konfigurationsseite */
+#define EC_MAX_FMMUS 16 /**< Maximale Anzahl FMMUs pro Slave */
 
-/**
-   Maximale Anzahl der Prozessdatendomänen in einem Master
-*/
-#define EC_MAX_DOMAINS 10
-
-/**
-   NULL-Define, falls noch nicht definiert.
-*/
+#define EC_MASTER_MAX_DOMAINS 10 /**< Maximale Anzahl Domänen eines Masters */
 
 #ifndef NULL
-#define NULL ((void *) 0)
+#define NULL ((void *) 0) /**< NULL-Define, falls noch nicht definiert. */
 #endif
 
 /*****************************************************************************/
 
 /**
-   EtherCAT-Kommando-Typ
-*/
-
-typedef enum
-{
-  EC_COMMAND_NONE = 0x00, /**< Dummy */
-  EC_COMMAND_APRD = 0x01, /**< Auto-increment physical read */
-  EC_COMMAND_APWR = 0x02, /**< Auto-increment physical write */
-  EC_COMMAND_NPRD = 0x04, /**< Node-addressed physical read */
-  EC_COMMAND_NPWR = 0x05, /**< Node-addressed physical write */
-  EC_COMMAND_BRD = 0x07,  /**< Broadcast read */
-  EC_COMMAND_BWR = 0x08,  /**< Broadcast write */
-  EC_COMMAND_LRW = 0x0C   /**< Logical read/write */
-}
-ec_command_type_t;
-
-/*****************************************************************************/
-
-/**
    Zustand eines EtherCAT-Slaves
 */
 
 typedef enum
 {
-  EC_SLAVE_STATE_UNKNOWN = 0x00, /**< Status unbekannt */
-  EC_SLAVE_STATE_INIT = 0x01,    /**< Init-Zustand (Keine Mailbox-
-                                    Kommunikation, Kein I/O) */
-  EC_SLAVE_STATE_PREOP = 0x02,   /**< Pre-Operational (Mailbox-
-                                    Kommunikation, Kein I/O) */
-  EC_SLAVE_STATE_SAVEOP = 0x04,  /**< Save-Operational (Mailbox-
-                                    Kommunikation und Input Update) */
-  EC_SLAVE_STATE_OP = 0x08,      /**< Operational, (Mailbox-
-                                    Kommunikation und Input/Output Update) */
-  EC_ACK = 0x10      /**< Acknoledge-Bit beim Zustandswechsel
-                        (dies ist kein eigener Zustand) */
+    EC_SLAVE_STATE_UNKNOWN = 0x00, /**< Status unbekannt */
+    EC_SLAVE_STATE_INIT = 0x01,    /**< Init-Zustand (Keine Mailbox-
+                                      Kommunikation, Kein I/O) */
+    EC_SLAVE_STATE_PREOP = 0x02,   /**< Pre-Operational (Mailbox-
+                                      Kommunikation, Kein I/O) */
+    EC_SLAVE_STATE_SAVEOP = 0x04,  /**< Save-Operational (Mailbox-
+                                      Kommunikation und Input Update) */
+    EC_SLAVE_STATE_OP = 0x08,      /**< Operational, (Mailbox-
+                                      Kommunikation und Input/Output Update) */
+    EC_ACK = 0x10                  /**< Acknoledge-Bit beim Zustandswechsel
+                                      (dies ist kein eigener Zustand) */
 }
 ec_slave_state_t;
 
 /*****************************************************************************/
 
 #endif
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:4 ***
+;;; End: ***
+*/
--- a/master/master.c	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/master.c	Thu Feb 23 09:58:50 2006 +0000
@@ -20,17 +20,7 @@
 #include "slave.h"
 #include "types.h"
 #include "device.h"
-#include "command.h"
-
-/*****************************************************************************/
-
-// Prototypen
-
-int ec_simple_send(ec_master_t *, ec_command_t *);
-int ec_simple_receive(ec_master_t *, ec_command_t *);
-void ec_output_debug_data(const ec_master_t *);
-int ec_sii_read(ec_master_t *, unsigned short, unsigned short, unsigned int *);
-void ec_output_lost_frames(ec_master_t *);
+#include "frame.h"
 
 /*****************************************************************************/
 
@@ -38,21 +28,17 @@
    Konstruktor des EtherCAT-Masters.
 */
 
-void ec_master_init(ec_master_t *master
-                    /**< Zeiger auf den zu initialisierenden EtherCAT-Master */
-                    )
-{
-  master->bus_slaves = NULL;
-  master->bus_slaves_count = 0;
-  master->device_registered = 0;
-  master->command_index = 0x00;
-  master->tx_data_length = 0;
-  master->rx_data_length = 0;
-  master->domain_count = 0;
-  master->debug_level = 0;
-  master->bus_time = 0;
-  master->frames_lost = 0;
-  master->t_lost_output = 0;
+void ec_master_init(ec_master_t *master /**< EtherCAT-Master */)
+{
+    master->slaves = NULL;
+    master->slave_count = 0;
+    master->device_registered = 0;
+    master->command_index = 0x00;
+    master->domain_count = 0;
+    master->debug_level = 0;
+    master->bus_time = 0;
+    master->frames_lost = 0;
+    master->t_lost_output = 0;
 }
 
 /*****************************************************************************/
@@ -64,24 +50,16 @@
    auf das Slave-Array und gibt die Prozessdaten frei.
 */
 
-void ec_master_clear(ec_master_t *master
-                     /**< Zeiger auf den zu löschenden Master */
-                     )
-{
-  if (master->bus_slaves) {
-    kfree(master->bus_slaves);
-    master->bus_slaves = NULL;
-  }
-
-  ec_device_clear(&master->device);
-
-  master->domain_count = 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Setzt den Master in den Ausgangszustand.
+void ec_master_clear(ec_master_t *master /**< EtherCAT-Master */)
+{
+    ec_master_reset(master);
+    ec_device_clear(&master->device);
+}
+
+/*****************************************************************************/
+
+/**
+   Setzt den Master zurück in den Ausgangszustand.
 
    Bei einem "release" sollte immer diese Funktion aufgerufen werden,
    da sonst Slave-Liste, Domains, etc. weiter existieren.
@@ -91,20 +69,28 @@
                      /**< Zeiger auf den zurückzusetzenden Master */
                      )
 {
-  if (master->bus_slaves) {
-    kfree(master->bus_slaves);
-    master->bus_slaves = NULL;
-  }
-
-  master->bus_slaves_count = 0;
-  master->command_index = 0;
-  master->tx_data_length = 0;
-  master->rx_data_length = 0;
-  master->domain_count = 0;
-  master->debug_level = 0;
-  master->bus_time = 0;
-  master->frames_lost = 0;
-  master->t_lost_output = 0;
+    unsigned int i;
+
+    if (master->slaves) {
+        for (i = 0; i < master->slave_count; i++) {
+            ec_slave_clear(master->slaves + i);
+        }
+        kfree(master->slaves);
+        master->slaves = NULL;
+    }
+    master->slave_count = 0;
+
+    for (i = 0; i < master->domain_count; i++) {
+        ec_domain_clear(master->domains[i]);
+        kfree(master->domains[i]);
+    }
+    master->domain_count = 0;
+
+    master->command_index = 0;
+    master->debug_level = 0;
+    master->bus_time = 0;
+    master->frames_lost = 0;
+    master->t_lost_output = 0;
 }
 
 /*****************************************************************************/
@@ -118,17 +104,17 @@
 
 int ec_master_open(ec_master_t *master /**< Der EtherCAT-Master */)
 {
-  if (!master->device_registered) {
-    printk(KERN_ERR "EtherCAT: No device registered!\n");
-    return -1;
-  }
-
-  if (ec_device_open(&master->device) < 0) {
-    printk(KERN_ERR "EtherCAT: Could not open device!\n");
-    return -1;
-  }
-
-  return 0;
+    if (!master->device_registered) {
+        printk(KERN_ERR "EtherCAT: No device registered!\n");
+        return -1;
+    }
+
+    if (ec_device_open(&master->device) < 0) {
+        printk(KERN_ERR "EtherCAT: Could not open device!\n");
+        return -1;
+    }
+
+    return 0;
 }
 
 /*****************************************************************************/
@@ -139,232 +125,15 @@
 
 void ec_master_close(ec_master_t *master /**< EtherCAT-Master */)
 {
-  if (!master->device_registered) {
-    printk(KERN_WARNING "EtherCAT: Warning -"
-           " Trying to close an unregistered device!\n");
-    return;
-  }
-
-  if (ec_device_close(&master->device) < 0) {
-    printk(KERN_WARNING "EtherCAT: Warning - Could not close device!\n");
-  }
-}
-
-/*****************************************************************************/
-
-/**
-   Sendet ein einzelnes Kommando in einem Frame und
-   wartet auf dessen Empfang.
-
-   \return 0 bei Erfolg, sonst < 0
-*/
-
-int ec_simple_send_receive(ec_master_t *master,
-                           /**< EtherCAT-Master */
-                           ec_command_t *cmd
-                           /**< Kommando zum Senden/Empfangen */
-                           )
-{
-  unsigned int tries_left;
-
-  if (unlikely(ec_simple_send(master, cmd) < 0))
-    return -1;
-
-  tries_left = 20;
-
-  do
-  {
-    udelay(1);
-    ec_device_call_isr(&master->device);
-    tries_left--;
-  }
-  while (unlikely(master->device.state == EC_DEVICE_STATE_SENT && tries_left));
-
-  if (unlikely(ec_simple_receive(master, cmd) < 0))
-    return -1;
-
-  return 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Sendet ein einzelnes Kommando in einem Frame.
-
-   \return 0 bei Erfolg, sonst < 0
-*/
-
-int ec_simple_send(ec_master_t *master, /**< EtherCAT-Master */
-                   ec_command_t *cmd /**< Kommando zum Senden */
-                   )
-{
-  unsigned int length, framelength, i;
-
-  if (unlikely(master->debug_level > 0)) {
-    printk(KERN_DEBUG "EtherCAT: ec_simple_send\n");
-  }
-
-  if (unlikely(cmd->state != EC_COMMAND_STATE_READY)) {
-    printk(KERN_WARNING "EtherCAT: cmd not in ready state!\n");
-  }
-
-  length = cmd->data_length + 12;
-  framelength = length + 2;
-
-  if (unlikely(framelength > EC_FRAME_SIZE)) {
-    printk(KERN_ERR "EtherCAT: Frame too long (%i)!\n", framelength);
-    return -1;
-  }
-
-  if (framelength < 46) framelength = 46;
-
-  if (unlikely(master->debug_level > 0)) {
-    printk(KERN_DEBUG "EtherCAT: Frame length: %i\n", framelength);
-  }
-
-  master->tx_data[0] = length & 0xFF;
-  master->tx_data[1] = ((length & 0x700) >> 8) | 0x10;
-
-  cmd->index = master->command_index;
-  master->command_index = (master->command_index + 1) % 0x0100;
-
-  if (unlikely(master->debug_level > 0)) {
-    printk(KERN_DEBUG "EtherCAT: Sending command index 0x%X\n", cmd->index);
-  }
-
-  cmd->state = EC_COMMAND_STATE_SENT;
-
-  master->tx_data[2 + 0] = cmd->type;
-  master->tx_data[2 + 1] = cmd->index;
-  master->tx_data[2 + 2] = cmd->address.raw[0];
-  master->tx_data[2 + 3] = cmd->address.raw[1];
-  master->tx_data[2 + 4] = cmd->address.raw[2];
-  master->tx_data[2 + 5] = cmd->address.raw[3];
-  master->tx_data[2 + 6] = cmd->data_length & 0xFF;
-  master->tx_data[2 + 7] = (cmd->data_length & 0x700) >> 8;
-  master->tx_data[2 + 8] = 0x00;
-  master->tx_data[2 + 9] = 0x00;
-
-  if (likely(cmd->type == EC_COMMAND_APWR
-             || cmd->type == EC_COMMAND_NPWR
-             || cmd->type == EC_COMMAND_BWR
-             || cmd->type == EC_COMMAND_LRW)) // Write commands
-  {
-    for (i = 0; i < cmd->data_length; i++)
-      master->tx_data[2 + 10 + i] = cmd->data[i];
-  }
-  else // Read commands
-  {
-    for (i = 0; i < cmd->data_length; i++) master->tx_data[2 + 10 + i] = 0x00;
-  }
-
-  master->tx_data[2 + 10 + cmd->data_length] = 0x00;
-  master->tx_data[2 + 11 + cmd->data_length] = 0x00;
-
-  // Pad with zeros
-  for (i = cmd->data_length + 12 + 2; i < 46; i++) master->tx_data[i] = 0x00;
-
-  master->tx_data_length = framelength;
-
-  if (unlikely(master->debug_level > 0)) {
-    printk(KERN_DEBUG "EtherCAT: Device send...\n");
-  }
-
-  // Send frame
-  if (unlikely(ec_device_send(&master->device, master->tx_data,
-                              framelength) != 0)) {
-    printk(KERN_ERR "EtherCAT: Could not send!\n");
-    return -1;
-  }
-
-  if (unlikely(master->debug_level > 0)) {
-    printk(KERN_DEBUG "EtherCAT: ec_simple_send done.\n");
-  }
-
-  return 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Wartet auf den Empfang eines einzeln gesendeten
-   Kommandos.
-
-   \return 0 bei Erfolg, sonst < 0
-*/
-
-int ec_simple_receive(ec_master_t *master, /**< EtherCAT-Master */
-                      ec_command_t *cmd /**< Gesendetes Kommando */
-                      )
-{
-  unsigned int length;
-  int ret;
-  unsigned char command_type, command_index;
-
-  if (unlikely((ret = ec_device_receive(&master->device,
-                                        master->rx_data)) < 0))
-    return -1;
-
-  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");
-    ec_output_debug_data(master);
-    return -1;
-  }
-
-  // Länge des gesamten Frames prüfen
-  length = ((master->rx_data[1] & 0x07) << 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");
-    ec_output_debug_data(master);
-    return -1;
-  }
-
-  command_type = master->rx_data[2];
-  command_index = master->rx_data[2 + 1];
-  length = (master->rx_data[2 + 6] & 0xFF)
-    | ((master->rx_data[2 + 7] & 0x07) << 8);
-
-  if (unlikely(master->rx_data_length - 2 < length + 12)) {
-    printk(KERN_ERR "EtherCAT: Received frame with"
-           " incomplete command data!\n");
-    ec_output_debug_data(master);
-    return -1;
-  }
-
-  if (likely(cmd->state == EC_COMMAND_STATE_SENT
-             && cmd->type == command_type
-             && cmd->index == command_index
-             && cmd->data_length == length))
-  {
-    cmd->state = EC_COMMAND_STATE_RECEIVED;
-
-    // Empfangene Daten in Kommandodatenspeicher kopieren
-    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));
-
-    if (unlikely(master->debug_level > 1)) {
-      ec_output_debug_data(master);
-    }
-  }
-  else
-  {
-    printk(KERN_WARNING "EtherCAT: WARNING - Send/Receive anomaly!\n");
-    ec_output_debug_data(master);
-  }
-
-  master->device.state = EC_DEVICE_STATE_READY;
-
-  return 0;
+    if (!master->device_registered) {
+        printk(KERN_WARNING "EtherCAT: Warning -"
+               " Trying to close an unregistered device!\n");
+        return;
+    }
+
+    if (ec_device_close(&master->device) < 0) {
+        printk(KERN_WARNING "EtherCAT: Warning - Could not close device!\n");
+    }
 }
 
 /*****************************************************************************/
@@ -377,319 +146,86 @@
 
 int ec_scan_for_slaves(ec_master_t *master /**< EtherCAT-Master */)
 {
-  ec_command_t cmd;
-  ec_slave_t *slave;
-  unsigned int i, j;
-  unsigned char data[2];
-
-  // Determine number of slaves on bus
-
-  ec_command_broadcast_read(&cmd, 0x0000, 4);
-
-  if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-    return -1;
-
-  master->bus_slaves_count = cmd.working_counter;
-  printk("EtherCAT: Found %i slaves on bus.\n", master->bus_slaves_count);
-
-  if (!master->bus_slaves_count) return 0;
-
-  if (!(master->bus_slaves = (ec_slave_t *) kmalloc(master->bus_slaves_count
-                                                    * sizeof(ec_slave_t),
-                                                    GFP_KERNEL))) {
-    printk(KERN_ERR "EtherCAT: Could not allocate memory for bus slaves!\n");
-    return -1;
-  }
-
-  // For every slave in the list
-  for (i = 0; i < master->bus_slaves_count; i++)
-  {
-    slave = master->bus_slaves + i;
-
-    ec_slave_init(slave);
-
-    // Set ring position
-
-    slave->ring_position = -i;
-    slave->station_address = i + 1;
-
-    // Write station address
-
-    data[0] = slave->station_address & 0x00FF;
-    data[1] = (slave->station_address & 0xFF00) >> 8;
-
-    ec_command_position_write(&cmd, slave->ring_position, 0x0010, 2, data);
-
-    if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-      return -1;
-
-    if (unlikely(cmd.working_counter != 1)) {
-      printk(KERN_ERR "EtherCAT: Slave %i did not repond while writing"
-             " station address!\n", i);
-      return -1;
-    }
-
-    // Read base data
-
-    ec_command_read(&cmd, slave->station_address, 0x0000, 4);
-
-    if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-      return -1;
-
-    if (unlikely(cmd.working_counter != 1)) {
-      printk(KERN_ERR "EtherCAT: Slave %i did not respond while reading base"
-             " data!\n", i);
-      return -1;
-    }
-
-    // Get base data
-
-    slave->base_type = cmd.data[0];
-    slave->base_revision = cmd.data[1];
-    slave->base_build = cmd.data[2] | (cmd.data[3] << 8);
-
-    // Read identification from "Slave Information Interface" (SII)
-
-    if (unlikely(ec_sii_read(master, slave->station_address, 0x0008,
-                             &slave->sii_vendor_id) != 0)) {
-      printk(KERN_ERR "EtherCAT: Could not read SII vendor id!\n");
-      return -1;
-    }
-
-    if (unlikely(ec_sii_read(master, slave->station_address, 0x000A,
-                             &slave->sii_product_code) != 0)) {
-      printk(KERN_ERR "EtherCAT: Could not read SII product code!\n");
-      return -1;
-    }
-
-    if (unlikely(ec_sii_read(master, slave->station_address, 0x000C,
-                             &slave->sii_revision_number) != 0)) {
-      printk(KERN_ERR "EtherCAT: Could not read SII revision number!\n");
-      return -1;
-    }
-
-    if (unlikely(ec_sii_read(master, slave->station_address, 0x000E,
-                             &slave->sii_serial_number) != 0)) {
-      printk(KERN_ERR "EtherCAT: Could not read SII serial number!\n");
-      return -1;
-    }
-
-    // Search for identification in "database"
-
-    for (j = 0; j < slave_ident_count; j++)
+    ec_frame_t frame;
+    ec_slave_t *slave;
+    ec_slave_ident_t *ident;
+    unsigned int i;
+    unsigned char data[2];
+
+    if (master->slaves || master->slave_count) {
+        printk(KERN_ERR "EtherCAT: Slave scan already done!\n");
+        return -1;
+    }
+
+    // Determine number of slaves on bus
+
+    ec_frame_init_brd(&frame, master, 0x0000, 4);
+    if (unlikely(ec_frame_send_receive(&frame) < 0)) return -1;
+
+    master->slave_count = frame.working_counter;
+    printk("EtherCAT: Found %i slaves on bus.\n", master->slave_count);
+
+    if (!master->slave_count) return 0;
+
+    if (!(master->slaves = (ec_slave_t *) kmalloc(master->slave_count
+                                                      * sizeof(ec_slave_t),
+                                                      GFP_KERNEL))) {
+        printk(KERN_ERR "EtherCAT: Could not allocate memory for bus"
+               " slaves!\n");
+        return -1;
+    }
+
+    // Init slaves
+    for (i = 0; i < master->slave_count; i++) {
+        slave = master->slaves + i;
+        ec_slave_init(slave, master);
+        slave->ring_position = i;
+        slave->station_address = i + 1;
+    }
+
+    // For every slave in the list
+    for (i = 0; i < master->slave_count; i++)
     {
-      if (unlikely(slave_idents[j].vendor_id == slave->sii_vendor_id
-                   && slave_idents[j].product_code == slave->sii_product_code))
-      {
-        slave->type = slave_idents[j].type;
-        break;
-      }
-    }
-
-    if (unlikely(!slave->type)) {
-      printk(KERN_WARNING "EtherCAT: Unknown slave device (vendor 0x%08X, code"
-             " 0x%08X) at position %i.\n", slave->sii_vendor_id,
-             slave->sii_product_code, i);
-      return 0;
-    }
-  }
-
-  return 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Liest Daten aus dem Slave-Information-Interface
-   eines EtherCAT-Slaves.
-
-   \return 0 bei Erfolg, sonst < 0
-*/
-
-int ec_sii_read(ec_master_t *master,
-                /**< EtherCAT-Master */
-                unsigned short int node_address,
-                /**< Knotenadresse des Slaves */
-                unsigned short int offset,
-                /**< Adresse des zu lesenden SII-Registers */
-                unsigned int *target
-                /**< Zeiger auf einen 4 Byte großen Speicher zum Ablegen der
-                   Daten */
-                )
-{
-  ec_command_t cmd;
-  unsigned char data[10];
-  unsigned int tries_left;
-
-  // Initiate read operation
-
-  data[0] = 0x00;
-  data[1] = 0x01;
-  data[2] = offset & 0xFF;
-  data[3] = (offset & 0xFF00) >> 8;
-  data[4] = 0x00;
-  data[5] = 0x00;
-
-  ec_command_write(&cmd, node_address, 0x502, 6, data);
-
-  if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-    return -1;
-
-  if (unlikely(cmd.working_counter != 1)) {
-    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
-  // in das Datenregister und löscht daraufhin ein Busy-Bit. Solange
-  // den Status auslesen, bis das Bit weg ist.
-
-  tries_left = 100;
-  while (likely(tries_left))
-  {
-    udelay(10);
-
-    ec_command_read(&cmd, node_address, 0x502, 10);
-
-    if (unlikely(ec_simple_send_receive(master, &cmd) != 0))
-      return -1;
-
-    if (unlikely(cmd.working_counter != 1)) {
-      printk(KERN_ERR "EtherCAT: SII-read status -"
-             " Slave %04X did not respond!\n", node_address);
-      return -1;
-    }
-
-    if (likely((cmd.data[1] & 0x81) == 0)) {
-      memcpy(target, cmd.data + 6, 4);
-      break;
-    }
-
-    tries_left--;
-  }
-
-  if (unlikely(!tries_left)) {
-    printk(KERN_WARNING "EtherCAT: SSI-read. Slave %04X timed out!\n",
-           node_address);
-    return -1;
-  }
-
-  return 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Ändert den Zustand eines Slaves.
-
-   \return 0 bei Erfolg, sonst < 0
-*/
-
-int ec_state_change(ec_master_t *master,
-                    /**<EtherCAT-Master */
-                    ec_slave_t *slave,
-                    /**< Slave, dessen Zustand geändert werden soll */
-                    unsigned char state_and_ack
-                    /**< Neuer Zustand, evtl. mit gesetztem Acknowledge-Flag */
-                    )
-{
-  ec_command_t cmd;
-  unsigned char data[2];
-  unsigned int tries_left;
-
-  data[0] = state_and_ack;
-  data[1] = 0x00;
-
-  ec_command_write(&cmd, slave->station_address, 0x0120, 2, data);
-
-  if (unlikely(ec_simple_send_receive(master, &cmd) != 0)) {
-    printk(KERN_ERR "EtherCAT: Could not set state %02X - Unable to send!\n",
-           state_and_ack);
-    return -1;
-  }
-
-  if (unlikely(cmd.working_counter != 1)) {
-    printk(KERN_ERR "EtherCAT: Could not set state %02X - Slave %i did not"
-           " respond!\n", state_and_ack, slave->ring_position * (-1));
-    return -1;
-  }
-
-  tries_left = 100;
-  while (likely(tries_left))
-  {
-    udelay(10);
-
-    ec_command_read(&cmd, slave->station_address, 0x0130, 2);
-
-    if (unlikely(ec_simple_send_receive(master, &cmd) != 0)) {
-      printk(KERN_ERR "EtherCAT: Could not check state %02X - Unable to"
-             " send!\n", state_and_ack);
-      return -1;
-    }
-
-    if (unlikely(cmd.working_counter != 1)) {
-      printk(KERN_ERR "EtherCAT: Could not check state %02X - Device %i did"
-             " not respond!\n", state_and_ack, slave->ring_position * (-1));
-      return -1;
-    }
-
-    if (unlikely(cmd.data[0] & 0x10)) { // State change error
-      printk(KERN_ERR "EtherCAT: Could not set state %02X - Device %i refused"
-             " state change (code %02X)!\n", state_and_ack,
-             slave->ring_position * (-1), cmd.data[0]);
-      return -1;
-    }
-
-    if (likely(cmd.data[0] == (state_and_ack & 0x0F))) {
-      // State change successful
-      break;
-    }
-
-    tries_left--;
-  }
-
-  if (unlikely(!tries_left)) {
-    printk(KERN_ERR "EtherCAT: Could not check state %02X of slave %i -"
-           " Timeout while checking!\n", state_and_ack,
-           slave->ring_position * (-1));
-    return -1;
-  }
-
-  return 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Gibt Frame-Inhalte zwecks Debugging aus.
-*/
-
-void ec_output_debug_data(const ec_master_t *master /**< EtherCAT-Master */)
-{
-  unsigned int i;
-
-  printk(KERN_DEBUG "EtherCAT: tx_data content (%i Bytes):\n",
-         master->tx_data_length);
-
-  printk(KERN_DEBUG);
-  for (i = 0; i < master->tx_data_length; i++)
-  {
-    printk("%02X ", master->tx_data[i]);
-    if ((i + 1) % 16 == 0) printk("\n" KERN_DEBUG);
-  }
-  printk("\n");
-
-  printk(KERN_DEBUG "EtherCAT: rx_data content (%i Bytes):\n",
-         master->rx_data_length);
-
-  printk(KERN_DEBUG);
-  for (i = 0; i < master->rx_data_length; i++)
-  {
-    printk("%02X ", master->rx_data[i]);
-    if ((i + 1) % 16 == 0) printk("\n" KERN_DEBUG);
-  }
-  printk("\n");
+        slave = master->slaves + i;
+
+        // Write station address
+        data[0] = slave->station_address & 0x00FF;
+        data[1] = (slave->station_address & 0xFF00) >> 8;
+
+        ec_frame_init_apwr(&frame, master, slave->ring_position, 0x0010, 2,
+                           data);
+
+        if (unlikely(ec_frame_send_receive(&frame) < 0)) return -1;
+
+        if (unlikely(frame.working_counter != 1)) {
+            printk(KERN_ERR "EtherCAT: Slave %i did not repond while writing"
+                   " station address!\n", i);
+            return -1;
+        }
+
+        // Fetch all slave information
+        if (ec_slave_fetch(slave)) return -1;
+
+        // Search for identification in "database"
+        ident = slave_idents;
+        while (ident) {
+            if (unlikely(ident->vendor_id == slave->sii_vendor_id
+                         && ident->product_code == slave->sii_product_code)) {
+                slave->type = ident->type;
+                break;
+            }
+            ident++;
+        }
+
+        if (!slave->type) {
+            printk(KERN_WARNING "EtherCAT: Unknown slave device (vendor"
+                   " 0x%08X, code 0x%08X) at position %i.\n",
+                   slave->sii_vendor_id, slave->sii_product_code, i);
+            return 0;
+        }
+    }
+
+    return 0;
 }
 
 /*****************************************************************************/
@@ -700,16 +236,17 @@
 
 void ec_output_lost_frames(ec_master_t *master /**< EtherCAT-Master */)
 {
-  unsigned long int t;
-
-  if (master->frames_lost) {
-    rdtscl(t);
-    if ((t - master->t_lost_output) / cpu_khz > 1000) {
-      printk(KERN_ERR "EtherCAT: %u frame(s) LOST!\n", master->frames_lost);
-      master->frames_lost = 0;
-      master->t_lost_output = t;
-    }
-  }
+    unsigned long int t;
+
+    if (master->frames_lost) {
+        rdtscl(t);
+        if ((t - master->t_lost_output) / cpu_khz > 1000) {
+            printk(KERN_ERR "EtherCAT: %u frame(s) LOST!\n",
+                   master->frames_lost);
+            master->frames_lost = 0;
+            master->t_lost_output = t;
+        }
+    }
 }
 
 /*****************************************************************************/
@@ -733,69 +270,129 @@
                        /**< Address-String */
                        )
 {
-  unsigned long first, second;
-  char *remainder, *remainder2;
-  unsigned int i;
-  int coupler_idx, slave_idx;
-  ec_slave_t *slave;
-
-  if (!address || address[0] == 0) return NULL;
-
-  if (address[0] == '#') {
-    printk(KERN_ERR "EtherCAT: Bus ID - #<SSID> not implemented yet!\n");
+    unsigned long first, second;
+    char *remainder, *remainder2;
+    unsigned int i;
+    int coupler_idx, slave_idx;
+    ec_slave_t *slave;
+
+    if (!address || address[0] == 0) return NULL;
+
+    if (address[0] == '#') {
+        printk(KERN_ERR "EtherCAT: Bus ID \"%s\" - #<SSID> not implemented"
+               " yet!\n", address);
+        return NULL;
+    }
+
+    first = simple_strtoul(address, &remainder, 0);
+    if (remainder == address) {
+        printk(KERN_ERR "EtherCAT: Bus ID \"%s\" - First number empty!\n",
+               address);
+        return NULL;
+    }
+
+    if (!remainder[0]) { // absolute position
+        if (first < master->slave_count) {
+            return master->slaves + first;
+        }
+
+        printk(KERN_ERR "EtherCAT: Bus ID \"%s\" - Absolute position"
+               " illegal!\n", address);
+    }
+
+    else if (remainder[0] == ':') { // field position
+
+        remainder++;
+        second = simple_strtoul(remainder, &remainder2, 0);
+
+        if (remainder2 == remainder) {
+            printk(KERN_ERR "EtherCAT: Bus ID \"%s\" - Sencond number"
+                   " empty!\n", address);
+            return NULL;
+        }
+
+        if (remainder2[0]) {
+            printk(KERN_ERR "EtherCAT: Bus ID \"%s\" - Illegal trailer"
+                   " (2)!\n", address);
+            return NULL;
+        }
+
+        coupler_idx = -1;
+        slave_idx = 0;
+        for (i = 0; i < master->slave_count; i++, slave_idx++) {
+            slave = master->slaves + i;
+            if (!slave->type) continue;
+
+            if (strcmp(slave->type->vendor_name, "Beckhoff") == 0 &&
+                strcmp(slave->type->product_name, "EK1100") == 0) {
+                coupler_idx++;
+                slave_idx = 0;
+            }
+
+            if (coupler_idx == first && slave_idx == second) return slave;
+        }
+    }
+
+    else {
+        printk(KERN_ERR "EtherCAT: Bus ID \"%s\" - Illegal trailer!\n",
+               address);
+    }
+
     return NULL;
-  }
-
-  first = simple_strtoul(address, &remainder, 0);
-  if (remainder == address) {
-    printk(KERN_ERR "EtherCAT: Bus ID - First number empty!\n");
-    return NULL;
-  }
-
-  if (!remainder[0]) { // absolute position
-    if (first < master->bus_slaves_count) {
-      return master->bus_slaves + first;
-    }
-
-    printk(KERN_ERR "EtherCAT: Bus ID - Absolute position illegal!\n");
-  }
-
-  else if (remainder[0] == ':') { // field position
-
-    remainder++;
-    second = simple_strtoul(remainder, &remainder2, 0);
-
-    if (remainder2 == remainder) {
-      printk(KERN_ERR "EtherCAT: Bus ID - Sencond number empty!\n");
-      return NULL;
-    }
-
-    if (remainder2[0]) {
-      printk(KERN_ERR "EtherCAT: Bus ID - Illegal trailer (2)!\n");
-      return NULL;
-    }
-
-    coupler_idx = -1;
-    slave_idx = 0;
-    for (i = 0; i < master->bus_slaves_count; i++, slave_idx++) {
-      slave = master->bus_slaves + i;
-      if (!slave->type) continue;
-
-      if (strcmp(slave->type->vendor_name, "Beckhoff") == 0 &&
-          strcmp(slave->type->product_name, "EK1100") == 0) {
-        coupler_idx++;
-        slave_idx = 0;
-      }
-
-      if (coupler_idx == first && slave_idx == second) return slave;
-    }
-  }
-
-  else {
-    printk(KERN_ERR "EtherCAT: Bus ID - Illegal trailer!\n");
-  }
-
-  return NULL;
+}
+
+/*****************************************************************************/
+
+/**
+   Initialisiert eine Sync-Manager-Konfigurationsseite.
+
+   Der mit \a data referenzierte Speicher muss mindestens EC_SYNC_SIZE Bytes
+   groß sein.
+*/
+
+void ec_sync_config(const ec_sync_t *sync, /**< Sync-Manager */
+                    uint8_t *data /**> Zeiger auf Konfigurationsspeicher */
+                    )
+{
+    data[0] = sync->physical_start_address & 0xFF;
+    data[1] = (sync->physical_start_address >> 8) & 0xFF;
+    data[2] = sync->size & 0xFF;
+    data[3] = (sync->size >> 8) & 0xFF;
+    data[4] = sync->control_byte;
+    data[5] = 0x00;
+    data[6] = 0x01; // enable
+    data[7] = 0x00;
+}
+
+/*****************************************************************************/
+
+/**
+   Initialisiert eine FMMU-Konfigurationsseite.
+
+   Der mit \a data referenzierte Speicher muss mindestens EC_FMMU_SIZE Bytes
+   groß sein.
+*/
+
+void ec_fmmu_config(const ec_fmmu_t *fmmu, /**< Sync-Manager */
+                    uint8_t *data /**> Zeiger auf Konfigurationsspeicher */
+                    )
+{
+    data[0] = fmmu->logical_start_address & 0xFF;
+    data[1] = (fmmu->logical_start_address >> 8) & 0xFF;
+    data[2] = (fmmu->logical_start_address >> 16) & 0xFF;
+    data[3] = (fmmu->logical_start_address >> 24) & 0xFF;
+    data[4] = fmmu->sync->size & 0xFF;
+    data[5] = (fmmu->sync->size >> 8) & 0xFF;
+    data[6] = 0x00; // Logical start bit
+    data[7] = 0x07; // Logical end bit
+    data[8] = fmmu->sync->physical_start_address & 0xFF;
+    data[9] = (fmmu->sync->physical_start_address >> 8) & 0xFF;
+    data[10] = 0x00; // Physical start bit
+    data[11] = (fmmu->sync->control_byte & 0x04) ? 0x02 : 0x01;
+    data[12] = 0x01; // Enable
+    data[13] = 0x00; // res.
+    data[14] = 0x00; // res.
+    data[15] = 0x00; // res.
 }
 
 /******************************************************************************
@@ -805,133 +402,37 @@
  *****************************************************************************/
 
 /**
-   Registriert einen Slave beim Master.
-
-   \return Zeiger auf den Slave bei Erfolg, sonst NULL
-*/
-
-ec_slave_t *EtherCAT_rt_register_slave(ec_master_t *master,
-                                       /**< EtherCAT-Master */
-                                       const char *address,
-                                       /**< ASCII-Addresse des Slaves, siehe
-                                          auch ec_address() */
-                                       const char *vendor_name,
-                                       /**< Herstellername */
-                                       const char *product_name,
-                                       /**< Produktname */
-                                       int domain
-                                       /**< Domäne */
-                                       )
-{
-  ec_slave_t *slave;
-  const ec_slave_type_t *type;
-  ec_domain_t *dom;
-  unsigned int j;
-
-  if (domain < 0) {
-    printk(KERN_ERR "EtherCAT: Invalid domain: %i\n", domain);
-    return NULL;
-  }
-
-  if ((slave = ec_address(master, address)) == NULL) {
-    printk(KERN_ERR "EtherCAT: Illegal address: \"%s\"\n", address);
-    return NULL;
-  }
-
-  if (slave->registered) {
-    printk(KERN_ERR "EtherCAT: Slave \"%s\" (position %i) has already been"
-           " registered!\n", address, slave->ring_position * (-1));
-    return NULL;
-  }
-
-  if (!slave->type) {
-    printk(KERN_ERR "EtherCAT: Slave \"%s\" (position %i) has unknown type!\n",
-           address, slave->ring_position * (-1));
-    return NULL;
-  }
-
-  type = slave->type;
-
-  if (strcmp(vendor_name, type->vendor_name) ||
-      strcmp(product_name, type->product_name)) {
-    printk(KERN_ERR "Invalid Slave Type! Requested: \"%s %s\", found: \"%s"
-           " %s\".\n", vendor_name, product_name, type->vendor_name,
-           type->product_name);
-    return NULL;
-  }
-
-  // Check, if process data domain already exists...
-  dom = NULL;
-  for (j = 0; j < master->domain_count; j++) {
-    if (domain == master->domains[j].number) {
-      dom = master->domains + j;
-      break;
-    }
-  }
-
-  // Create process data domain
-  if (!dom) {
-    if (master->domain_count > EC_MAX_DOMAINS - 1) {
-      printk(KERN_ERR "EtherCAT: Too many domains!\n");
-      return NULL;
-    }
-
-    dom = master->domains + master->domain_count;
-    ec_domain_init(dom);
-    dom->number = domain;
-    dom->logical_offset = master->domain_count * EC_FRAME_SIZE;
+   Registriert eine neue Domäne.
+
+   \return Zeiger auf die Domäne bei Erfolg, sonst NULL.
+*/
+
+ec_domain_t *EtherCAT_rt_master_register_domain(ec_master_t *master,
+                                                /**< Domäne */
+                                                ec_domain_mode_t mode,
+                                                /**< Modus */
+                                                unsigned int timeout_us
+                                                /**< Timeout */
+                                                )
+{
+    ec_domain_t *domain;
+
+    if (master->domain_count >= EC_MASTER_MAX_DOMAINS) {
+        printk(KERN_ERR "EtherCAT: Maximum number of domains reached!\n");
+        return NULL;
+    }
+
+    if (!(domain = (ec_domain_t *) kmalloc(sizeof(ec_domain_t), GFP_KERNEL))) {
+        printk(KERN_ERR "EthertCAT: Error allocating domain memory!\n");
+        return NULL;
+    }
+
+    ec_domain_init(domain, master, mode, timeout_us);
+    master->domains[master->domain_count] = domain;
     master->domain_count++;
-  }
-
-  if (dom->data_size + type->process_data_size > EC_FRAME_SIZE - 14) {
-    printk(KERN_ERR "EtherCAT: Oversized domain %i: %i / %i Bytes!\n",
-           dom->number, dom->data_size + type->process_data_size,
-           EC_FRAME_SIZE - 14);
-    return NULL;
-  }
-
-  slave->process_data = dom->data + dom->data_size;
-  slave->logical_address = dom->data_size;
-  slave->registered = 1;
-
-  dom->data_size += type->process_data_size;
-
-  return slave;
-}
-
-/*****************************************************************************/
-
-/**
-   Registriert eine ganze Liste von Slaves beim Master.
-
-   \return 0 bei Erfolg, sonst < 0
-*/
-
-int EtherCAT_rt_register_slave_list(ec_master_t *master,
-                                    /**< EtherCAT-Master */
-                                    const ec_slave_init_t *slaves,
-                                    /**< Array von Slave-Initialisierungs-
-                                       strukturen */
-                                    unsigned int count
-                                    /**< Anzahl der Strukturen in \a slaves */
-                                    )
-{
-  unsigned int i;
-
-  for (i = 0; i < count; i++)
-  {
-    if ((*(slaves[i].slave_ptr) =
-         EtherCAT_rt_register_slave(master, slaves[i].address,
-                                    slaves[i].vendor_name,
-                                    slaves[i].product_name,
-                                    slaves[i].domain)) == NULL)
-      return -1;
-  }
-
-  return 0;
-}
-
-/*****************************************************************************/
+
+    return domain;
+}
 
 /**
    Konfiguriert alle Slaves und setzt den Operational-Zustand.
@@ -943,313 +444,148 @@
    \return 0 bei Erfolg, sonst < 0
 */
 
-int EtherCAT_rt_activate_slaves(ec_master_t *master /**< EtherCAT-Master */)
-{
-  unsigned int i;
-  ec_slave_t *slave;
-  ec_command_t cmd;
-  const ec_slave_type_t *type;
-  unsigned char fmmu[16];
-  unsigned char data[256];
-
-  for (i = 0; i < master->bus_slaves_count; i++)
-  {
-    slave = master->bus_slaves + i;
-
-    if (unlikely(ec_state_change(master, slave, EC_SLAVE_STATE_INIT) != 0))
-      return -1;
-
-    // Check if slave was registered...
-    if (!slave->registered) {
-      printk(KERN_INFO "EtherCAT: Slave %i was not registered.\n", i);
-      continue;
-    }
-
-    type = slave->type;
-
-    // Resetting FMMU's
-
-    memset(data, 0x00, 256);
-
-    ec_command_write(&cmd, slave->station_address, 0x0600, 256, data);
-
-    if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-      return -1;
-
-    if (unlikely(cmd.working_counter != 1)) {
-      printk(KERN_ERR "EtherCAT: Resetting FMMUs - Slave %04X did not"
-             " respond!\n", slave->station_address);
-      return -1;
-    }
-
-    // Resetting Sync Manager channels
-
-    if (type->features != EC_NOSYNC_SLAVE)
+int EtherCAT_rt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
+{
+    unsigned int i, j;
+    ec_slave_t *slave;
+    ec_frame_t frame;
+    const ec_sync_t *sync;
+    const ec_slave_type_t *type;
+    const ec_fmmu_t *fmmu;
+    uint8_t data[256];
+    uint32_t domain_offset;
+
+    // Domains erstellen
+    domain_offset = 0;
+    for (i = 0; i < master->domain_count; i++) {
+        ec_domain_t *domain = master->domains[i];
+        if (ec_domain_alloc(domain, domain_offset)) {
+            printk(KERN_INFO "EtherCAT: Failed to allocate domain %i!\n", i);
+            return -1;
+        }
+        printk(KERN_INFO "EtherCAT: Domain %i - Allocated %i bytes (%i"
+               " Frame(s))\n", i, domain->data_size,
+               domain->data_size / EC_MAX_FRAME_SIZE + 1);
+        domain_offset += domain->data_size;
+    }
+
+    // Slaves aktivieren
+    for (i = 0; i < master->slave_count; i++)
     {
-      memset(data, 0x00, 256);
-
-      ec_command_write(&cmd, slave->station_address, 0x0800, 256, data);
-
-      if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-        return -1;
-
-      if (unlikely(cmd.working_counter != 1)) {
-        printk(KERN_ERR "EtherCAT: Resetting SMs - Slave %04X did not"
-               " respond!\n", slave->station_address);
-        return -1;
-      }
-    }
-
-    // Init Mailbox communication
-
-    if (type->features == EC_MAILBOX_SLAVE)
+        slave = master->slaves + i;
+
+        // Change state to INIT
+        if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT)))
+            return -1;
+
+        // Check if slave was registered...
+        if (!slave->type || !slave->registered) {
+            printk(KERN_INFO "EtherCAT: Slave %i was not registered.\n", i);
+            continue;
+        }
+
+        type = slave->type;
+
+        // Resetting FMMU's
+        if (slave->base_fmmu_count) {
+            memset(data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
+            ec_frame_init_npwr(&frame, master, slave->station_address, 0x0600,
+                               EC_FMMU_SIZE * slave->base_fmmu_count, data);
+            if (unlikely(ec_frame_send_receive(&frame) < 0)) return -1;
+            if (unlikely(frame.working_counter != 1)) {
+                printk(KERN_ERR "EtherCAT: Resetting FMMUs - Slave %i did"
+                       " not respond!\n", slave->ring_position);
+                return -1;
+            }
+        }
+
+        // Resetting Sync Manager channels
+        if (slave->base_sync_count) {
+            memset(data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
+            ec_frame_init_npwr(&frame, master, slave->station_address, 0x0800,
+                               EC_SYNC_SIZE * slave->base_sync_count, data);
+            if (unlikely(ec_frame_send_receive(&frame) < 0)) return -1;
+            if (unlikely(frame.working_counter != 1)) {
+                printk(KERN_ERR "EtherCAT: Resetting SMs - Slave %i did not"
+                       " respond!\n", slave->ring_position);
+                return -1;
+            }
+        }
+
+        // Set Sync Managers
+        for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++)
+        {
+            sync = type->sync_managers[j];
+
+            ec_sync_config(sync, data);
+            ec_frame_init_npwr(&frame, master, slave->station_address,
+                               0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE, data);
+
+            if (unlikely(ec_frame_send_receive(&frame))) return -1;
+
+            if (unlikely(frame.working_counter != 1)) {
+                printk(KERN_ERR "EtherCAT: Setting sync manager %i - Slave"
+                       " %i did not respond!\n", j, slave->ring_position);
+                return -1;
+            }
+        }
+
+        // Change state to PREOP
+        if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_PREOP)))
+            return -1;
+
+        // Set FMMUs
+        for (j = 0; j < slave->fmmu_count; j++)
+        {
+            fmmu = &slave->fmmus[j];
+
+            ec_fmmu_config(fmmu, data);
+            ec_frame_init_npwr(&frame, master, slave->station_address,
+                               0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE, data);
+
+            if (unlikely(ec_frame_send_receive(&frame))) return -1;
+
+            if (unlikely(frame.working_counter != 1)) {
+                printk(KERN_ERR "EtherCAT: Setting FMMU %i - Slave %i did not"
+                       " respond!\n", j, slave->ring_position);
+                return -1;
+            }
+        }
+
+        // Change state to SAVEOP
+        if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_SAVEOP)))
+            return -1;
+
+        // Change state to OP
+        if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_OP)))
+            return -1;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Setzt alle Slaves zurück in den Init-Zustand.
+
+   \return 0 bei Erfolg, sonst < 0
+*/
+
+int EtherCAT_rt_master_deactivate(ec_master_t *master /**< EtherCAT-Master */)
+{
+    ec_slave_t *slave;
+    unsigned int i;
+
+    for (i = 0; i < master->slave_count; i++)
     {
-      if (type->sm0)
-      {
-        ec_command_write(&cmd, slave->station_address, 0x0800, 8, type->sm0);
-
-        if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-          return -1;
-
-        if (unlikely(cmd.working_counter != 1)) {
-          printk(KERN_ERR "EtherCAT: Setting SM0 - Slave %04X did not"
-                 " respond!\n", slave->station_address);
-          return -1;
-        }
-      }
-
-      if (type->sm1)
-      {
-        ec_command_write(&cmd, slave->station_address, 0x0808, 8, type->sm1);
-
-        if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-          return -1;
-
-        if (unlikely(cmd.working_counter != 1)) {
-          printk(KERN_ERR "EtherCAT: Setting SM1 -"
-                 " Slave %04X did not respond!\n",
-                 slave->station_address);
-          return -1;
-        }
-      }
-    }
-
-    // Change state to PREOP
-
-    if (unlikely(ec_state_change(master, slave, EC_SLAVE_STATE_PREOP) != 0))
-      return -1;
-
-    // Set FMMU's
-
-    if (type->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, type->fmmu0, 16);
-
-      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;
-
-      ec_command_write(&cmd, slave->station_address, 0x0600, 16, fmmu);
-
-      if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-        return -1;
-
-      if (unlikely(cmd.working_counter != 1)) {
-        printk(KERN_ERR "EtherCAT: Setting FMMU0 - Slave %04X did not"
-               " respond!\n", slave->station_address);
-        return -1;
-      }
-    }
-
-    // Set Sync Managers
-
-    if (type->features != EC_MAILBOX_SLAVE)
-    {
-      if (type->sm0)
-      {
-        ec_command_write(&cmd, slave->station_address, 0x0800, 8, type->sm0);
-
-        if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-          return -1;
-
-        if (unlikely(cmd.working_counter != 1)) {
-          printk(KERN_ERR "EtherCAT: Setting SM0 - Slave %04X did not"
-                 " respond!\n", slave->station_address);
-          return -1;
-        }
-      }
-
-      if (type->sm1)
-      {
-        ec_command_write(&cmd, slave->station_address, 0x0808, 8, type->sm1);
-
-        if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-          return -1;
-
-        if (unlikely(cmd.working_counter != 1)) {
-          printk(KERN_ERR "EtherCAT: Setting SM1 - Slave %04X did not"
-                 " respond!\n", slave->station_address);
-          return -1;
-        }
-      }
-    }
-
-    if (type->sm2)
-    {
-      ec_command_write(&cmd, slave->station_address, 0x0810, 8, type->sm2);
-
-      if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-        return -1;
-
-      if (unlikely(cmd.working_counter != 1)) {
-        printk(KERN_ERR "EtherCAT: Setting SM2 - Slave %04X did not"
-               " respond!\n", slave->station_address);
-        return -1;
-      }
-    }
-
-    if (type->sm3)
-    {
-      ec_command_write(&cmd, slave->station_address, 0x0818, 8, type->sm3);
-
-      if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
-        return -1;
-
-      if (unlikely(cmd.working_counter != 1)) {
-        printk(KERN_ERR "EtherCAT: Setting SM3 - Slave %04X did not"
-               " respond!\n", slave->station_address);
-        return -1;
-      }
-    }
-
-    // Change state to SAVEOP
-    if (unlikely(ec_state_change(master, slave, EC_SLAVE_STATE_SAVEOP) != 0))
-      return -1;
-
-    // Change state to OP
-    if (unlikely(ec_state_change(master, slave, EC_SLAVE_STATE_OP) != 0))
-      return -1;
-  }
-
-  return 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Setzt alle Slaves zurück in den Init-Zustand.
-
-   \return 0 bei Erfolg, sonst < 0
-*/
-
-int EtherCAT_rt_deactivate_slaves(ec_master_t *master /**< EtherCAT-Master */)
-{
-  ec_slave_t *slave;
-  unsigned int i;
-
-  for (i = 0; i < master->bus_slaves_count; i++)
-  {
-    slave = master->bus_slaves + i;
-
-    if (unlikely(ec_state_change(master, slave, EC_SLAVE_STATE_INIT) != 0))
-      return -1;
-  }
-
-  return 0;
-}
-
-/*****************************************************************************/
-
-/**
-   Sendet und empfängt Prozessdaten der angegebenen Domäne
-
-   \return 0 bei Erfolg, sonst < 0
-*/
-
-int EtherCAT_rt_domain_xio(ec_master_t *master,
-                           /**< EtherCAT-Master */
-                           unsigned int domain,
-                           /**< Domäne */
-                           unsigned int timeout_us
-                           /**< Timeout in Mikrosekunden */
-                           )
-{
-  unsigned int i;
-  ec_domain_t *dom;
-  unsigned long start_ticks, end_ticks, timeout_ticks;
-
-  ec_output_lost_frames(master); // Evtl. verlorene Frames ausgeben
-
-  // Domäne bestimmen
-  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;
-  }
-
-  ec_command_logical_read_write(&dom->command, dom->logical_offset,
-                                dom->data_size, dom->data);
-
-  rdtscl(start_ticks); // Sendezeit nehmen
-
-  if (unlikely(ec_simple_send(master, &dom->command) < 0)) {
-    printk(KERN_ERR "EtherCAT: Could not send process data command!\n");
-    return -1;
-  }
-
-  timeout_ticks = timeout_us * cpu_khz / 1000;
-
-  // Warten
-  do {
-    ec_device_call_isr(&master->device);
-    rdtscl(end_ticks); // Empfangszeit nehmen
-  }
-  while (unlikely(master->device.state == EC_DEVICE_STATE_SENT
-                  && end_ticks - start_ticks < timeout_ticks));
-
-  master->bus_time = (end_ticks - start_ticks) * 1000 / cpu_khz;
-
-  if (unlikely(end_ticks - start_ticks >= timeout_ticks)) {
-    master->device.state = EC_DEVICE_STATE_READY;
-    master->frames_lost++;
-    ec_output_lost_frames(master);
-    return -1;
-  }
-
-  if (unlikely(ec_simple_receive(master, &dom->command) < 0)) {
-    printk(KERN_ERR "EtherCAT: Could not receive cyclic command!\n");
-    return -1;
-  }
-
-  if (unlikely(dom->command.state != EC_COMMAND_STATE_RECEIVED)) {
-    printk(KERN_WARNING "EtherCAT: Process data command not received!\n");
-    return -1;
-  }
-
-  if (dom->command.working_counter != dom->response_count) {
-    dom->response_count = dom->command.working_counter;
-    printk(KERN_INFO "EtherCAT: Domain %i State change - %i slaves"
-           " responding.\n", dom->number, dom->response_count);
-  }
-
-  // Daten vom Kommando in den Prozessdatenspeicher kopieren
-  memcpy(dom->data, dom->command.data, dom->data_size);
-
-  return 0;
+        slave = master->slaves + i;
+
+        if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT) != 0))
+            return -1;
+    }
+
+    return 0;
 }
 
 /*****************************************************************************/
@@ -1263,28 +599,50 @@
    - 2: Komplette Frame-Inhalte
 */
 
-void EtherCAT_rt_debug_level(ec_master_t *master,
-                             /**< EtherCAT-Master */
-                             int level
-                             /**< Debug-Level */
-                             )
-{
-  master->debug_level = level;
-}
-
-/*****************************************************************************/
-
-EXPORT_SYMBOL(EtherCAT_rt_register_slave);
-EXPORT_SYMBOL(EtherCAT_rt_register_slave_list);
-EXPORT_SYMBOL(EtherCAT_rt_activate_slaves);
-EXPORT_SYMBOL(EtherCAT_rt_deactivate_slaves);
-EXPORT_SYMBOL(EtherCAT_rt_domain_xio);
-EXPORT_SYMBOL(EtherCAT_rt_debug_level);
+void EtherCAT_rt_master_debug(ec_master_t *master,
+                              /**< EtherCAT-Master */
+                              int level
+                              /**< Debug-Level */
+                              )
+{
+    master->debug_level = level;
+
+    printk(KERN_INFO "EtherCAT: Master debug level set to %i.\n", level);
+}
+
+/*****************************************************************************/
+
+/**
+   Gibt alle Informationen zum Master aus.
+*/
+
+void EtherCAT_rt_master_print(const ec_master_t *master
+                              /**< EtherCAT-Master */
+                              )
+{
+    unsigned int i;
+
+    printk(KERN_INFO "EtherCAT: *** Begin master information ***\n");
+
+    for (i = 0; i < master->slave_count; i++) {
+        ec_slave_print(&master->slaves[i]);
+    }
+
+    printk(KERN_INFO "EtherCAT: *** End master information ***\n");
+}
+
+/*****************************************************************************/
+
+EXPORT_SYMBOL(EtherCAT_rt_master_register_domain);
+EXPORT_SYMBOL(EtherCAT_rt_master_activate);
+EXPORT_SYMBOL(EtherCAT_rt_master_deactivate);
+EXPORT_SYMBOL(EtherCAT_rt_master_debug);
+EXPORT_SYMBOL(EtherCAT_rt_master_print);
 
 /*****************************************************************************/
 
 /* Emacs-Konfiguration
 ;;; Local Variables: ***
-;;; c-basic-offset:2 ***
+;;; c-basic-offset:4 ***
 ;;; End: ***
 */
--- a/master/master.h	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/master.h	Thu Feb 23 09:58:50 2006 +0000
@@ -13,7 +13,7 @@
 
 #include "device.h"
 #include "slave.h"
-#include "command.h"
+#include "frame.h"
 #include "domain.h"
 
 /*****************************************************************************/
@@ -27,25 +27,18 @@
 
 struct ec_master
 {
-  ec_slave_t *bus_slaves; /**< Array von Slaves auf dem Bus */
-  unsigned int bus_slaves_count; /**< Anzahl Slaves auf dem Bus */
-  ec_device_t device; /**< EtherCAT-Gerät */
-  unsigned int device_registered; /**< Ein Geraet hat sich registriert. */
-  unsigned char command_index; /**< Aktueller Kommando-Index */
-  unsigned char tx_data[EC_FRAME_SIZE]; /**< Statischer Speicher
-                                           für zu sendende Daten */
-  unsigned int tx_data_length; /**< Länge der Daten im Sendespeicher */
-  unsigned char rx_data[EC_FRAME_SIZE]; /**< Statische Speicher für
-                                           eine Kopie des Rx-Buffers
-                                           im EtherCAT-Gerät */
-  unsigned int rx_data_length; /**< Länge der Daten im Empfangsspeicher */
-  ec_domain_t domains[EC_MAX_DOMAINS]; /** Prozessdatendomänen */
-  unsigned int domain_count;
-  int debug_level; /**< Debug-Level im Master-Code */
-  unsigned int bus_time; /**< Letzte Bus-Zeit in Mikrosekunden */
-  unsigned int frames_lost; /**< Anzahl verlorene Frames */
-  unsigned long t_lost_output; /*<< Timer-Ticks bei der letzten Ausgabe von
-                                 verlorenen Frames */
+    ec_slave_t *slaves; /**< Array von Slaves auf dem Bus */
+    unsigned int slave_count; /**< Anzahl Slaves auf dem Bus */
+    ec_device_t device; /**< EtherCAT-Gerät */
+    unsigned int device_registered; /**< Ein Geraet hat sich registriert. */
+    uint8_t command_index; /**< Aktueller Kommando-Index */
+    ec_domain_t *domains[EC_MASTER_MAX_DOMAINS]; /** Prozessdatendomänen */
+    unsigned int domain_count;
+    int debug_level; /**< Debug-Level im Master-Code */
+    unsigned int bus_time; /**< Letzte Bus-Zeit in Mikrosekunden */
+    unsigned int frames_lost; /**< Anzahl verlorene Frames */
+    unsigned long t_lost_output; /*<< Timer-Ticks bei der letzten Ausgabe von
+                                   verlorenen Frames */
 };
 
 /*****************************************************************************/
@@ -63,8 +56,9 @@
 int ec_scan_for_slaves(ec_master_t *);
 ec_slave_t *ec_address(const ec_master_t *, const char *);
 
-// Data
-int ec_simple_send_receive(ec_master_t *, ec_command_t *);
+// Misc
+void ec_output_debug_data(const ec_master_t *);
+void ec_output_lost_frames(ec_master_t *);
 
 /*****************************************************************************/
 
@@ -72,6 +66,6 @@
 
 /* Emacs-Konfiguration
 ;;; Local Variables: ***
-;;; c-basic-offset:2 ***
+;;; c-basic-offset:4 ***
 ;;; End: ***
 */
--- a/master/module.c	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/module.c	Thu Feb 23 09:58:50 2006 +0000
@@ -69,46 +69,45 @@
 
 int __init ec_init_module(void)
 {
-  unsigned int i;
-
-  printk(KERN_ERR "EtherCAT: Master driver, %s\n", COMPILE_INFO);
-
-  if (ec_master_count < 1) {
-    printk(KERN_ERR "EtherCAT: Error - Illegal"
-           " ec_master_count: %i\n", ec_master_count);
-    return -1;
-  }
-
-  printk(KERN_ERR "EtherCAT: Initializing %i EtherCAT master(s)...\n",
-         ec_master_count);
-
-  if ((ec_masters =
-       (ec_master_t *) kmalloc(sizeof(ec_master_t)
-                               * ec_master_count,
-                               GFP_KERNEL)) == NULL) {
-    printk(KERN_ERR "EtherCAT: Could not allocate"
-           " memory for EtherCAT master(s)!\n");
-    return -1;
-  }
-
-  if ((ec_masters_reserved =
-       (int *) kmalloc(sizeof(int) * ec_master_count,
-                       GFP_KERNEL)) == NULL) {
-    printk(KERN_ERR "EtherCAT: Could not allocate"
-           " memory for reservation flags!\n");
-    kfree(ec_masters);
-    return -1;
-  }
-
-  for (i = 0; i < ec_master_count; i++)
-  {
-    ec_master_init(&ec_masters[i]);
-    ec_masters_reserved[i] = 0;
-  }
-
-  printk(KERN_ERR "EtherCAT: Master driver initialized.\n");
-
-  return 0;
+    unsigned int i;
+
+    printk(KERN_ERR "EtherCAT: Master driver, %s\n", COMPILE_INFO);
+
+    if (ec_master_count < 1) {
+        printk(KERN_ERR "EtherCAT: Error - Illegal"
+               " ec_master_count: %i\n", ec_master_count);
+        return -1;
+    }
+
+    printk(KERN_ERR "EtherCAT: Initializing %i EtherCAT master(s)...\n",
+           ec_master_count);
+
+    if ((ec_masters =
+         (ec_master_t *) kmalloc(sizeof(ec_master_t)
+                                 * ec_master_count,
+                                 GFP_KERNEL)) == NULL) {
+        printk(KERN_ERR "EtherCAT: Could not allocate"
+               " memory for EtherCAT master(s)!\n");
+        return -1;
+    }
+
+    if ((ec_masters_reserved =
+         (int *) kmalloc(sizeof(int) * ec_master_count,
+                         GFP_KERNEL)) == NULL) {
+        printk(KERN_ERR "EtherCAT: Could not allocate"
+               " memory for reservation flags!\n");
+        kfree(ec_masters);
+        return -1;
+    }
+
+    for (i = 0; i < ec_master_count; i++) {
+        ec_master_init(ec_masters + i);
+        ec_masters_reserved[i] = 0;
+    }
+
+    printk(KERN_ERR "EtherCAT: Master driver initialized.\n");
+
+    return 0;
 }
 
 /*****************************************************************************/
@@ -121,26 +120,22 @@
 
 void __exit ec_cleanup_module(void)
 {
-  unsigned int i;
-
-  printk(KERN_ERR "EtherCAT: Cleaning up master driver...\n");
-
-  if (ec_masters)
-  {
-    for (i = 0; i < ec_master_count; i++)
-    {
-      if (ec_masters_reserved[i]) {
-        printk(KERN_WARNING "EtherCAT: Warning -"
-               " Master %i is still in use!\n", i);
-      }
-
-      ec_master_clear(&ec_masters[i]);
-    }
-
-    kfree(ec_masters);
-  }
-
-  printk(KERN_ERR "EtherCAT: Master driver cleaned up.\n");
+    unsigned int i;
+
+    printk(KERN_ERR "EtherCAT: Cleaning up master driver...\n");
+
+    if (ec_masters) {
+        for (i = 0; i < ec_master_count; i++) {
+            if (ec_masters_reserved[i]) {
+                printk(KERN_WARNING "EtherCAT: Warning -"
+                       " Master %i is still in use!\n", i);
+            }
+            ec_master_clear(&ec_masters[i]);
+        }
+        kfree(ec_masters);
+    }
+
+    printk(KERN_ERR "EtherCAT: Master driver cleaned up.\n");
 }
 
 /******************************************************************************
@@ -158,8 +153,8 @@
    @param module Zeiger auf das Modul (fuer try_module_lock())
 
    @return 0, wenn alles o.k.,
-           < 0, wenn bereits ein Geraet registriert oder das Geraet nicht
-                geoeffnet werden konnte.
+   < 0, wenn bereits ein Geraet registriert oder das Geraet nicht
+   geoeffnet werden konnte.
 */
 
 ec_device_t *EtherCAT_dev_register(unsigned int master_index,
@@ -168,42 +163,39 @@
                                                       struct pt_regs *),
                                    struct module *module)
 {
-  ec_device_t *ecd;
-  ec_master_t *master;
-
-  if (master_index >= ec_master_count) {
-    printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", master_index);
-    return NULL;
-  }
-
-  if (!dev) {
-    printk("EtherCAT: Device is NULL!\n");
-    return NULL;
-  }
-
-  master = ec_masters + master_index;
-
-  if (master->device_registered) {
-    printk(KERN_ERR "EtherCAT: Master %i already has a device!\n",
-           master_index);
-    return NULL;
-  }
-
-  ecd = &master->device;
-
-  if (ec_device_init(ecd) < 0) {
-    return NULL;
-  }
-
-  ecd->dev = dev;
-  ecd->tx_skb->dev = dev;
-  ecd->rx_skb->dev = dev;
-  ecd->isr = isr;
-  ecd->module = module;
-
-  master->device_registered = 1;
-
-  return ecd;
+    ec_device_t *ecd;
+    ec_master_t *master;
+
+    if (master_index >= ec_master_count) {
+        printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", master_index);
+        return NULL;
+    }
+
+    if (!dev) {
+        printk("EtherCAT: Device is NULL!\n");
+        return NULL;
+    }
+
+    master = ec_masters + master_index;
+
+    if (master->device_registered) {
+        printk(KERN_ERR "EtherCAT: Master %i already has a device!\n",
+               master_index);
+        return NULL;
+    }
+
+    ecd = &master->device;
+
+    if (ec_device_init(ecd) < 0) return NULL;
+
+    ecd->dev = dev;
+    ecd->tx_skb->dev = dev;
+    ecd->isr = isr;
+    ecd->module = module;
+
+    master->device_registered = 1;
+
+    return ecd;
 }
 
 /*****************************************************************************/
@@ -217,22 +209,23 @@
 
 void EtherCAT_dev_unregister(unsigned int master_index, ec_device_t *ecd)
 {
-  ec_master_t *master;
-
-  if (master_index >= ec_master_count) {
-    printk(KERN_WARNING "EtherCAT: Master %i does not exist!\n", master_index);
-    return;
-  }
-
-  master = ec_masters + master_index;
-
-  if (!master->device_registered || &master->device != ecd) {
-    printk(KERN_ERR "EtherCAT: Unable to unregister device!\n");
-    return;
-  }
-
-  master->device_registered = 0;
-  ec_device_clear(ecd);
+    ec_master_t *master;
+
+    if (master_index >= ec_master_count) {
+        printk(KERN_WARNING "EtherCAT: Master %i does not exist!\n",
+               master_index);
+        return;
+    }
+
+    master = ec_masters + master_index;
+
+    if (!master->device_registered || &master->device != ecd) {
+        printk(KERN_ERR "EtherCAT: Unable to unregister device!\n");
+        return;
+    }
+
+    master->device_registered = 0;
+    ec_device_clear(ecd);
 }
 
 /******************************************************************************
@@ -252,54 +245,54 @@
 
 ec_master_t *EtherCAT_rt_request_master(unsigned int index)
 {
-  ec_master_t *master;
-
-  if (index < 0 || index >= ec_master_count) {
-    printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index);
-    goto req_return;
-  }
-
-  if (ec_masters_reserved[index]) {
-    printk(KERN_ERR "EtherCAT: Master %i already in use!\n", index);
-    goto req_return;
-  }
-
-  master = &ec_masters[index];
-
-  if (!master->device_registered) {
-    printk(KERN_ERR "EtherCAT: Master %i has no device assigned yet!\n",
-           index);
-    goto req_return;
-  }
-
-  if (!try_module_get(master->device.module)) {
-    printk(KERN_ERR "EtherCAT: Could not reserve device module!\n");
-    goto req_return;
-  }
-
-  if (ec_master_open(master) < 0) {
-    printk(KERN_ERR "EtherCAT: Could not open device!\n");
-    goto req_module_put;
-  }
-
-  if (ec_scan_for_slaves(master) != 0) {
-    printk(KERN_ERR "EtherCAT: Could not scan for slaves!\n");
-    goto req_close;
-  }
-
-  ec_masters_reserved[index] = 1;
-  printk(KERN_INFO "EtherCAT: Reserved master %i.\n", index);
-
-  return master;
+    ec_master_t *master;
+
+    if (index < 0 || index >= ec_master_count) {
+        printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index);
+        goto req_return;
+    }
+
+    if (ec_masters_reserved[index]) {
+        printk(KERN_ERR "EtherCAT: Master %i already in use!\n", index);
+        goto req_return;
+    }
+
+    master = &ec_masters[index];
+
+    if (!master->device_registered) {
+        printk(KERN_ERR "EtherCAT: Master %i has no device assigned yet!\n",
+               index);
+        goto req_return;
+    }
+
+    if (!try_module_get(master->device.module)) {
+        printk(KERN_ERR "EtherCAT: Failed to reserve device module!\n");
+        goto req_return;
+    }
+
+    if (ec_master_open(master) < 0) {
+        printk(KERN_ERR "EtherCAT: Failed to open device!\n");
+        goto req_module_put;
+    }
+
+    if (ec_scan_for_slaves(master) != 0) {
+        printk(KERN_ERR "EtherCAT: Bus scan failed!\n");
+        goto req_close;
+    }
+
+    ec_masters_reserved[index] = 1;
+    printk(KERN_INFO "EtherCAT: Reserved master %i.\n", index);
+
+    return master;
 
  req_close:
-  ec_master_close(master);
+    ec_master_close(master);
 
  req_module_put:
-  module_put(master->device.module);
+    module_put(master->device.module);
 
  req_return:
-  return NULL;
+    return NULL;
 }
 
 /*****************************************************************************/
@@ -312,32 +305,32 @@
 
 void EtherCAT_rt_release_master(ec_master_t *master)
 {
-  unsigned int i;
-
-  for (i = 0; i < ec_master_count; i++)
-  {
-    if (&ec_masters[i] == master)
+    unsigned int i;
+
+    for (i = 0; i < ec_master_count; i++)
     {
-      if (!master->device_registered) {
-        printk(KERN_WARNING "EtherCAT: Could not release device"
-               "module because of no device!\n");
-        return;
-      }
-
-      ec_master_close(master);
-      ec_master_reset(master);
-
-      module_put(master->device.module);
-      ec_masters_reserved[i] = 0;
-
-      printk(KERN_INFO "EtherCAT: Released master %i.\n", i);
-
-      return;
-    }
-  }
-
-  printk(KERN_WARNING "EtherCAT: Master %X was never requested!\n",
-         (unsigned int) master);
+        if (&ec_masters[i] == master)
+        {
+            if (!master->device_registered) {
+                printk(KERN_WARNING "EtherCAT: Failed to release device"
+                       "module because of no device!\n");
+                return;
+            }
+
+            ec_master_close(master);
+            ec_master_reset(master);
+
+            module_put(master->device.module);
+            ec_masters_reserved[i] = 0;
+
+            printk(KERN_INFO "EtherCAT: Released master %i.\n", i);
+
+            return;
+        }
+    }
+
+    printk(KERN_WARNING "EtherCAT: Master %X was never requested!\n",
+           (unsigned int) master);
 }
 
 /*****************************************************************************/
@@ -354,6 +347,6 @@
 
 /* Emacs-Konfiguration
 ;;; Local Variables: ***
-;;; c-basic-offset:2 ***
+;;; c-basic-offset:4 ***
 ;;; End: ***
 */
--- a/master/slave.c	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/slave.c	Thu Feb 23 09:58:50 2006 +0000
@@ -9,48 +9,431 @@
  *****************************************************************************/
 
 #include <linux/module.h>
+#include <linux/delay.h>
 
 #include "globals.h"
 #include "slave.h"
+#include "frame.h"
 
 /*****************************************************************************/
 
 /**
    EtherCAT-Slave-Konstruktor.
-
-   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
-*/
-
-void ec_slave_init(ec_slave_t *slave)
-{
-  slave->base_type = 0;
-  slave->base_revision = 0;
-  slave->base_build = 0;
-  slave->ring_position = 0;
-  slave->station_address = 0;
-  slave->sii_vendor_id = 0;
-  slave->sii_product_code = 0;
-  slave->sii_revision_number = 0;
-  slave->sii_serial_number = 0;
-  slave->type = NULL;
-  slave->logical_address = 0;
-  slave->process_data = NULL;
-  slave->private_data = NULL;
-  slave->configure = NULL;
-  slave->registered = 0;
-  slave->domain = 0;
-  slave->error_reported = 0;
+*/
+
+void ec_slave_init(ec_slave_t *slave, /**< EtherCAT-Slave */
+                   ec_master_t *master /**< EtherCAT-Master */
+                   )
+{
+    slave->master = master;
+    slave->base_type = 0;
+    slave->base_revision = 0;
+    slave->base_build = 0;
+    slave->base_fmmu_count = 0;
+    slave->base_sync_count = 0;
+    slave->ring_position = 0;
+    slave->station_address = 0;
+    slave->sii_vendor_id = 0;
+    slave->sii_product_code = 0;
+    slave->sii_revision_number = 0;
+    slave->sii_serial_number = 0;
+    slave->type = NULL;
+    slave->registered = 0;
+    slave->fmmu_count = 0;
+}
+
+/*****************************************************************************/
+
+/**
+   EtherCAT-Slave-Destruktor.
+*/
+
+void ec_slave_clear(ec_slave_t *slave /**< EtherCAT-Slave */)
+{
+    // Nichts freizugeben
+}
+
+/*****************************************************************************/
+
+/**
+   Liest alle benötigten Informationen aus einem Slave.
+*/
+
+int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */)
+{
+    ec_frame_t frame;
+
+    // Read base data
+    ec_frame_init_nprd(&frame, slave->master, slave->station_address,
+                       0x0000, 6);
+
+    if (unlikely(ec_frame_send_receive(&frame))) return -1;
+
+    if (unlikely(frame.working_counter != 1)) {
+        printk(KERN_ERR "EtherCAT: Slave %i did not respond while reading base"
+               " data!\n", slave->ring_position);
+        return -1;
+    }
+
+    slave->base_type = frame.data[0];
+    slave->base_revision = frame.data[1];
+    slave->base_build = frame.data[2] | (frame.data[3] << 8);
+    slave->base_fmmu_count = frame.data[4];
+    slave->base_sync_count = frame.data[5];
+
+    if (slave->base_fmmu_count > EC_MAX_FMMUS)
+        slave->base_fmmu_count = EC_MAX_FMMUS;
+
+    // Read identification from "Slave Information Interface" (SII)
+
+    if (unlikely(ec_slave_sii_read(slave, 0x0008, &slave->sii_vendor_id))) {
+        printk(KERN_ERR "EtherCAT: Could not read SII vendor id!\n");
+        return -1;
+    }
+
+    if (unlikely(ec_slave_sii_read(slave, 0x000A, &slave->sii_product_code))) {
+        printk(KERN_ERR "EtherCAT: Could not read SII product code!\n");
+        return -1;
+    }
+
+    if (unlikely(ec_slave_sii_read(slave, 0x000C,
+                                   &slave->sii_revision_number))) {
+        printk(KERN_ERR "EtherCAT: Could not read SII revision number!\n");
+        return -1;
+    }
+
+    if (unlikely(ec_slave_sii_read(slave, 0x000E,
+                                   &slave->sii_serial_number))) {
+        printk(KERN_ERR "EtherCAT: Could not read SII serial number!\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Liest Daten aus dem Slave-Information-Interface
+   eines EtherCAT-Slaves.
+
+   \return 0 bei Erfolg, sonst < 0
+*/
+
+int ec_slave_sii_read(ec_slave_t *slave,
+                      /**< EtherCAT-Slave */
+                      unsigned short int offset,
+                      /**< Adresse des zu lesenden SII-Registers */
+                      unsigned int *target
+                      /**< Zeiger auf einen 4 Byte großen Speicher zum Ablegen
+                         der Daten */
+                      )
+{
+    ec_frame_t frame;
+    unsigned char data[10];
+    unsigned int tries_left;
+
+    // Initiate read operation
+
+    data[0] = 0x00;
+    data[1] = 0x01;
+    data[2] = offset & 0xFF;
+    data[3] = (offset & 0xFF00) >> 8;
+    data[4] = 0x00;
+    data[5] = 0x00;
+
+    ec_frame_init_npwr(&frame, slave->master, slave->station_address, 0x502, 6,
+                       data);
+
+    if (unlikely(ec_frame_send_receive(&frame))) return -1;
+
+    if (unlikely(frame.working_counter != 1)) {
+        printk(KERN_ERR "EtherCAT: SII-read - Slave %i did not respond!\n",
+               slave->ring_position);
+        return -1;
+    }
+
+    // Der Slave legt die Informationen des Slave-Information-Interface
+    // in das Datenregister und löscht daraufhin ein Busy-Bit. Solange
+    // den Status auslesen, bis das Bit weg ist.
+
+    tries_left = 100;
+    while (likely(tries_left))
+    {
+        udelay(10);
+
+        ec_frame_init_nprd(&frame, slave->master, slave->station_address, 0x502,
+                           10);
+
+        if (unlikely(ec_frame_send_receive(&frame))) return -1;
+
+        if (unlikely(frame.working_counter != 1)) {
+            printk(KERN_ERR "EtherCAT: SII-read status -"
+                   " Slave %i did not respond!\n", slave->ring_position);
+            return -1;
+        }
+
+        if (likely((frame.data[1] & 0x81) == 0)) {
+            memcpy(target, frame.data + 6, 4);
+            break;
+        }
+
+        tries_left--;
+    }
+
+    if (unlikely(!tries_left)) {
+        printk(KERN_WARNING "EtherCAT: SSI-read. Slave %i timed out!\n",
+               slave->ring_position);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Bestätigt einen Fehler beim Zustandswechsel.
+
+   FIXME Funktioniert noch nicht...
+*/
+
+void ec_slave_state_ack(ec_slave_t *slave,
+                        /**< Slave, dessen Zustand geändert werden soll */
+                        uint8_t state
+                        /**< Alter Zustand */
+                        )
+{
+    ec_frame_t frame;
+    unsigned char data[2];
+    unsigned int tries_left;
+
+    data[0] = state | EC_ACK;
+    data[1] = 0x00;
+
+    ec_frame_init_npwr(&frame, slave->master, slave->station_address, 0x0120,
+                       2, data);
+
+    if (unlikely(ec_frame_send_receive(&frame) != 0)) {
+        printk(KERN_ERR "EtherCAT: Could no acknowledge state %02X - Unable to"
+               " send!\n", state);
+        return;
+    }
+
+    if (unlikely(frame.working_counter != 1)) {
+        printk(KERN_ERR "EtherCAT: Could not acknowledge state %02X - Slave"
+               " %i did not respond!\n", state, slave->ring_position);
+        return;
+    }
+
+    tries_left = 100;
+    while (likely(tries_left))
+    {
+        udelay(10);
+
+        ec_frame_init_nprd(&frame, slave->master, slave->station_address,
+                           0x0130, 2);
+
+        if (unlikely(ec_frame_send_receive(&frame) != 0)) {
+            printk(KERN_ERR "EtherCAT: Could not check state acknowledgement"
+                   " %02X - Unable to send!\n", state);
+            return;
+        }
+
+        if (unlikely(frame.working_counter != 1)) {
+            printk(KERN_ERR "EtherCAT: Could not check state acknowledgement"
+                   " %02X - Slave %i did not respond!\n", state,
+                   slave->ring_position);
+            return;
+        }
+
+        if (unlikely(frame.data[0] != state)) {
+            printk(KERN_ERR "EtherCAT: Could not acknowledge state %02X on"
+                   " slave %i (code %02X)!\n", state, slave->ring_position,
+                   frame.data[0]);
+            return;
+        }
+
+        if (likely(frame.data[0] == state)) {
+            printk(KERN_INFO "EtherCAT: Acknowleged state %02X on slave %i.\n",
+                   state, slave->ring_position);
+            return;
+        }
+
+        tries_left--;
+    }
+
+    if (unlikely(!tries_left)) {
+        printk(KERN_ERR "EtherCAT: Could not check state acknowledgement %02X"
+               " of slave %i - Timeout while checking!\n", state,
+               slave->ring_position);
+        return;
+    }
+}
+
+/*****************************************************************************/
+
+/**
+   Ändert den Zustand eines Slaves.
+
+   \return 0 bei Erfolg, sonst < 0
+*/
+
+int ec_slave_state_change(ec_slave_t *slave,
+                          /**< Slave, dessen Zustand geändert werden soll */
+                          uint8_t state
+                          /**< Neuer Zustand */
+                          )
+{
+    ec_frame_t frame;
+    unsigned char data[2];
+    unsigned int tries_left;
+
+    data[0] = state;
+    data[1] = 0x00;
+
+    ec_frame_init_npwr(&frame, slave->master, slave->station_address, 0x0120,
+                       2, data);
+
+    if (unlikely(ec_frame_send_receive(&frame) != 0)) {
+        printk(KERN_ERR "EtherCAT: Could not set state %02X - Unable to"
+               " send!\n", state);
+        return -1;
+    }
+
+    if (unlikely(frame.working_counter != 1)) {
+        printk(KERN_ERR "EtherCAT: Could not set state %02X - Slave %i did not"
+               " respond!\n", state, slave->ring_position);
+        return -1;
+    }
+
+    tries_left = 100;
+    while (likely(tries_left))
+    {
+        udelay(10);
+
+        ec_frame_init_nprd(&frame, slave->master, slave->station_address,
+                           0x0130, 2);
+
+        if (unlikely(ec_frame_send_receive(&frame) != 0)) {
+            printk(KERN_ERR "EtherCAT: Could not check state %02X - Unable to"
+                   " send!\n", state);
+            return -1;
+        }
+
+        if (unlikely(frame.working_counter != 1)) {
+            printk(KERN_ERR "EtherCAT: Could not check state %02X - Slave %i"
+                   " did not respond!\n", state, slave->ring_position);
+            return -1;
+        }
+
+        if (unlikely(frame.data[0] & 0x10)) { // State change error
+            printk(KERN_ERR "EtherCAT: Could not set state %02X - Slave %i"
+                   " refused state change (code %02X)!\n", state,
+                   slave->ring_position, frame.data[0]);
+            ec_slave_state_ack(slave, frame.data[0] & 0x0F);
+            return -1;
+        }
+
+        if (likely(frame.data[0] == (state & 0x0F))) {
+            // State change successful
+            break;
+        }
+
+        tries_left--;
+    }
+
+    if (unlikely(!tries_left)) {
+        printk(KERN_ERR "EtherCAT: Could not check state %02X of slave %i -"
+               " Timeout while checking!\n", state,
+               slave->ring_position);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Merkt eine FMMU-Konfiguration vor.
+
+   Die FMMU wird so konfiguriert, dass sie den gesamten Datenbereich des
+   entsprechenden Sync-Managers abdeckt. Für jede Domäne werden separate
+   FMMUs konfiguriert.
+
+   Wenn die entsprechende FMMU bereits konfiguriert ist, wird dies als
+   Erfolg zurückgegeben.
+
+   \return 0 bei Erfolg, sonst < 0
+*/
+
+int ec_slave_set_fmmu(ec_slave_t *slave, /**< EtherCAT-Slave */
+                      const ec_domain_t *domain, /**< Domäne */
+                      const ec_sync_t *sync  /**< Sync-Manager */
+                      )
+{
+    unsigned int i;
+
+    // FMMU schon vorgemerkt?
+    for (i = 0; i < slave->fmmu_count; i++)
+        if (slave->fmmus[i].domain == domain && slave->fmmus[i].sync == sync)
+            return 0;
+
+    if (slave->fmmu_count >= slave->base_fmmu_count) {
+        printk(KERN_ERR "EtherCAT: Slave %i supports only %i FMMUs.\n",
+               slave->ring_position, slave->base_fmmu_count);
+        return -1;
+    }
+
+    slave->fmmus[slave->fmmu_count].domain = domain;
+    slave->fmmus[slave->fmmu_count].sync = sync;
+    slave->fmmus[slave->fmmu_count].logical_start_address = 0;
+    slave->fmmu_count++;
+    slave->registered = 1;
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/**
+   Gibt alle Informationen über einen EtherCAT-Slave aus.
+*/
+
+void ec_slave_print(const ec_slave_t *slave /**< EtherCAT-Slave */)
+{
+    printk(KERN_INFO "--- EtherCAT slave information ---\n");
+
+    if (slave->type) {
+        printk(KERN_INFO "  Vendor \"%s\", Product \"%s\": %s\n",
+               slave->type->vendor_name, slave->type->product_name,
+               slave->type->description);
+    }
+    else {
+        printk(KERN_INFO "  *** This slave has no type information! ***\n");
+    }
+
+    printk(KERN_INFO "  Ring position: %i, Station address: 0x%04X\n",
+           slave->ring_position, slave->station_address);
+
+    printk(KERN_INFO "  Base information:\n");
+    printk(KERN_INFO "    Type %u, Revision %i, Build %i\n",
+           slave->base_type, slave->base_revision, slave->base_build);
+    printk(KERN_INFO "    Supported FMMUs: %i, Sync managers: %i\n",
+           slave->base_fmmu_count, slave->base_sync_count);
+
+    printk(KERN_INFO "  Slave information interface:\n");
+    printk(KERN_INFO "    Vendor-ID: 0x%08X, Product code: 0x%08X\n",
+           slave->sii_vendor_id, slave->sii_product_code);
+    printk(KERN_INFO "    Revision number: 0x%08X, Serial number: 0x%08X\n",
+           slave->sii_revision_number, slave->sii_serial_number);
 }
 
 /*****************************************************************************/
 
 /* Emacs-Konfiguration
 ;;; Local Variables: ***
-;;; c-basic-offset:2 ***
+;;; c-basic-offset:4 ***
 ;;; End: ***
 */
--- a/master/slave.h	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/slave.h	Thu Feb 23 09:58:50 2006 +0000
@@ -15,12 +15,68 @@
 
 /*****************************************************************************/
 
-// ec_slave_t ist in EtherCAT_rt.h ...
+/**
+   FMMU-Konfiguration.
+*/
+
+typedef struct
+{
+    const ec_domain_t *domain;
+    const ec_sync_t *sync;
+    uint32_t logical_start_address;
+}
+ec_fmmu_t;
 
 /*****************************************************************************/
 
-// Slave construction and deletion
-void ec_slave_init(ec_slave_t *);
+/**
+   EtherCAT-Slave
+*/
+
+struct ec_slave
+{
+    ec_master_t *master; /**< EtherCAT-Master, zu dem der Slave gehört. */
+
+    // Addresses
+    uint16_t ring_position; /**< Position des Slaves im Bus */
+    uint16_t station_address; /**< Konfigurierte Slave-Adresse */
+
+    // Base data
+    uint8_t base_type; /**< Slave-Typ */
+    uint8_t base_revision; /**< Revision */
+    uint16_t base_build; /**< Build-Nummer */
+    uint16_t base_fmmu_count; /**< Anzahl unterstützter FMMUs */
+    uint16_t base_sync_count; /**< Anzahl unterstützter Sync-Manager */
+
+    // Slave information interface
+    uint32_t sii_vendor_id; /**< Identifikationsnummer des Herstellers */
+    uint32_t sii_product_code; /**< Herstellerspezifischer Produktcode */
+    uint32_t sii_revision_number; /**< Revisionsnummer */
+    uint32_t sii_serial_number; /**< Seriennummer der Klemme */
+
+    const ec_slave_type_t *type; /**< Zeiger auf die Beschreibung
+                                    des Slave-Typs */
+
+    uint8_t registered; /**< Der Slave wurde registriert */
+
+    ec_fmmu_t fmmus[EC_MAX_FMMUS]; /**< FMMU-Konfigurationen */
+    uint8_t fmmu_count; /**< Wieviele FMMUs schon benutzt sind. */
+};
+
+/*****************************************************************************/
+
+// Slave construction/destruction
+void ec_slave_init(ec_slave_t *, ec_master_t *);
+void ec_slave_clear(ec_slave_t *);
+
+// Slave control
+int ec_slave_fetch(ec_slave_t *);
+int ec_slave_sii_read(ec_slave_t *, unsigned short, unsigned int *);
+int ec_slave_state_change(ec_slave_t *, uint8_t);
+int ec_slave_set_fmmu(ec_slave_t *, const ec_domain_t *, const ec_sync_t *);
+
+// Misc
+void ec_slave_print(const ec_slave_t *);
 
 /*****************************************************************************/
 
@@ -28,6 +84,6 @@
 
 /* Emacs-Konfiguration
 ;;; Local Variables: ***
-;;; c-basic-offset:2 ***
+;;; c-basic-offset:4 ***
 ;;; End: ***
 */
--- a/master/types.c	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/types.c	Thu Feb 23 09:58:50 2006 +0000
@@ -15,134 +15,148 @@
 
 /*****************************************************************************/
 
-/*
-  Konfigurationen der Sync-Manager
-
-  Byte 1-2: Physical Start Address
-  Byte 3-4: Data Length
-  Byte   5: Control Byte
-  Byte   6: Status Byte (read only)
-  Byte 7-8: Enable
-*/
-
-unsigned char sm0_multi[] = {0x00, 0x18, 0xF6, 0x00, 0x26, 0x00, 0x01, 0x00};
-unsigned char sm1_multi[] = {0xF6, 0x18, 0xF6, 0x00, 0x22, 0x00, 0x01, 0x00};
-
-unsigned char sm0_1014[] = {0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00};
-
-unsigned char sm0_20xx[] = {0x00, 0x0F, 0x01, 0x00, 0x46, 0x00, 0x01, 0x00};
-
-unsigned char sm2_31xx[] = {0x00, 0x10, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00};
-unsigned char sm3_31xx[] = {0x00, 0x11, 0x06, 0x00, 0x20, 0x00, 0x01, 0x00};
-
-unsigned char sm2_41xx[] = {0x00, 0x10, 0x04, 0x00, 0x24, 0x00, 0x01, 0x00};
-
-unsigned char sm2_5001[] = {0x00, 0x10, 0x04, 0x00, 0x24, 0x00, 0x01, 0x00};
-unsigned char sm3_5001[] = {0x00, 0x11, 0x05, 0x00, 0x20, 0x00, 0x01, 0x00};
-
-unsigned char sm2_5101[] = {0x00, 0x10, 0x03, 0x00, 0x24, 0x00, 0x01, 0x00};
-unsigned char sm3_5101[] = {0x00, 0x11, 0x05, 0x00, 0x20, 0x00, 0x01, 0x00};
-
-/*
-  Konfigurationen der Memory-Management-Units
-
-  Byte   1-4: Logical Start Address (is set later)
-  Byte   5-6: Length
-  Byte     7: Logical start bit
-  Byte     8: Logical end bit
-  Byte  9-10: Physical start address
-  Byte    11: Physical start bit
-  Byte    12: Direction (1: in, 2: out)
-  Byte 13-14: Channel enable
-  Byte 15-16: Reserved
-*/
-
-unsigned char fmmu0_1014[] = {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07,
-                              0x00, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00};
-
-unsigned char fmmu0_20xx[] = {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07,
-                              0x00, 0x0F, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00};
-
-unsigned char fmmu0_31xx[] = {0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07,
-                              0x00, 0x11, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00};
-
-unsigned char fmmu0_41xx[] = {0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x07,
-                              0x00, 0x10, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00};
-
-unsigned char fmmu0_5001[] = {0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x07,
-                              0x00, 0x11, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00};
-
-unsigned char fmmu0_5101[] = {0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x07,
-                              0x00, 0x11, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00};
+const ec_sync_t mailbox_sm0 = {0x1800, 246, 0x26, {NULL}};
+const ec_sync_t mailbox_sm1 = {0x18F6, 246, 0x22, {NULL}};
 
 /*****************************************************************************/
 
 /* Klemmen-Objekte */
 
-ec_slave_type_t Beckhoff_EK1100 =
-{
-    "Beckhoff", "EK1100", "Bus Coupler",
-    EC_NOSYNC_SLAVE, NULL, NULL, NULL, NULL, NULL, 0
+/*****************************************************************************/
+
+const ec_slave_type_t Beckhoff_EK1100 = {
+    "Beckhoff", "EK1100", "Bus Coupler", EC_NOSYNC_SLAVE,
+    {NULL} // Keine Sync-Manager
 };
 
-ec_slave_type_t Beckhoff_EK1110 =
-{
-    "Beckhoff", "EK1110", "Extension terminal",
-    EC_NOSYNC_SLAVE, NULL, NULL, NULL, NULL, NULL, 0
+/*****************************************************************************/
+
+const ec_slave_type_t Beckhoff_EK1110 = {
+    "Beckhoff", "EK1110", "Extension terminal", EC_NOSYNC_SLAVE,
+    {NULL} // Keine Sync-Manager
 };
 
-ec_slave_type_t Beckhoff_EL1014 =
-{
-    "Beckhoff", "EL1014", "4x Digital Input",
-    EC_SIMPLE_SLAVE, sm0_1014, NULL, NULL, NULL, fmmu0_1014, 1
+/*****************************************************************************/
+
+const ec_field_t el1014_in = {ec_ipvalue, 1};
+
+const ec_sync_t el1014_sm0 = { // Inputs
+    0x1000, 1, 0x00,
+    {&el1014_in, NULL}
 };
 
-ec_slave_type_t Beckhoff_EL2004 =
-{
-    "Beckhoff", "EL2004", "4x Digital Output",
-    EC_SIMPLE_SLAVE, sm0_20xx, NULL, NULL, NULL, fmmu0_20xx, 1
+const ec_slave_type_t Beckhoff_EL1014 = {
+    "Beckhoff", "EL1014", "4x Digital Input", EC_SIMPLE_SLAVE,
+    {&el1014_sm0, NULL}
 };
 
-ec_slave_type_t Beckhoff_EL2032 =
-{
-    "Beckhoff", "EL2032", "2x Digital Output (2A)",
-    EC_SIMPLE_SLAVE, sm0_20xx, NULL, NULL, NULL, fmmu0_20xx, 1
+/*****************************************************************************/
+
+const ec_field_t el20XX_out = {ec_opvalue, 1};
+
+const ec_sync_t el20XX_sm0 = {
+    0x0F00, 1, 0x46,
+    {&el20XX_out, NULL}
 };
 
-ec_slave_type_t Beckhoff_EL3102 =
-{
-    "Beckhoff", "EL3102", "2x Analog Input diff.",
-    EC_MAILBOX_SLAVE, sm0_multi, sm1_multi, sm2_31xx, sm3_31xx, fmmu0_31xx, 6
+const ec_slave_type_t Beckhoff_EL2004 = {
+    "Beckhoff", "EL2004", "4x Digital Output", EC_SIMPLE_SLAVE,
+    {&el20XX_sm0, NULL}
 };
 
-ec_slave_type_t Beckhoff_EL3162 =
-{
-    "Beckhoff", "EL3162", "2x Analog Input",
-    EC_MAILBOX_SLAVE, sm0_multi, sm1_multi, sm2_31xx, sm3_31xx, fmmu0_31xx, 6
+const ec_slave_type_t Beckhoff_EL2032 = {
+    "Beckhoff", "EL2032", "2x Digital Output (2A)", EC_SIMPLE_SLAVE,
+    {&el20XX_sm0, NULL}
 };
 
-ec_slave_type_t Beckhoff_EL4102 =
-{
-    "Beckhoff", "EL4102", "2x Analog Output",
-    EC_MAILBOX_SLAVE, sm0_multi, sm1_multi, sm2_41xx, NULL, fmmu0_41xx, 4
+/*****************************************************************************/
+
+const ec_field_t el31X2_st1 = {ec_status,  1};
+const ec_field_t el31X2_ip1 = {ec_ipvalue, 2};
+const ec_field_t el31X2_st2 = {ec_status,  1};
+const ec_field_t el31X2_ip2 = {ec_ipvalue, 2};
+
+const ec_sync_t el31X2_sm2 = {
+    0x1000, 4, 0x24,
+    {NULL}
 };
 
-ec_slave_type_t Beckhoff_EL4132 =
-{
-    "Beckhoff", "EL4132", "2x Analog Output diff.",
-    EC_MAILBOX_SLAVE, sm0_multi, sm1_multi, sm2_41xx, NULL, fmmu0_41xx, 4
+const ec_sync_t el31X2_sm3 = {
+    0x1100, 6, 0x20,
+    {&el31X2_st1, &el31X2_ip1, &el31X2_st2, &el31X2_ip2, NULL}
 };
 
-ec_slave_type_t Beckhoff_EL5001 =
-{
-    "Beckhoff", "EL5001", "SSI-Interface",
-    EC_MAILBOX_SLAVE, sm0_multi, sm1_multi, sm2_5001, sm3_5001, fmmu0_5001, 5
+const ec_slave_type_t Beckhoff_EL3102 = {
+    "Beckhoff", "EL3102", "2x Analog Input diff.", EC_MAILBOX_SLAVE,
+    {&mailbox_sm0, &mailbox_sm1, &el31X2_sm2, &el31X2_sm2, NULL}
 };
 
-ec_slave_type_t Beckhoff_EL5101 =
+const ec_slave_type_t Beckhoff_EL3162 = {
+    "Beckhoff", "EL3102", "2x Analog Input", EC_MAILBOX_SLAVE,
+    {&mailbox_sm0, &mailbox_sm1, &el31X2_sm2, &el31X2_sm2, NULL}
+};
+
+/*****************************************************************************/
+
+const ec_field_t el41X2_op = {ec_opvalue, 2};
+
+const ec_sync_t el41X2_sm2 = {
+    0x1000, 4, 0x24,
+    {&el41X2_op, &el41X2_op, NULL}
+};
+
+const ec_slave_type_t Beckhoff_EL4102 = {
+    "Beckhoff", "EL4102", "2x Analog Output", EC_MAILBOX_SLAVE,
+    {&mailbox_sm0, &mailbox_sm1, &el41X2_sm2, NULL}
+};
+
+const ec_slave_type_t Beckhoff_EL4132 = {
+    "Beckhoff", "EL4132", "2x Analog Output diff.", EC_MAILBOX_SLAVE,
+    {&mailbox_sm0, &mailbox_sm1, &el41X2_sm2, NULL}
+};
+
+/*****************************************************************************/
+
+const ec_field_t el5001_st = {ec_status,  1};
+const ec_field_t el5001_ip = {ec_ipvalue, 4};
+
+const ec_sync_t el5001_sm2 = {
+    0x1000, 4, 0x24,
+    {NULL}
+};
+
+const ec_sync_t el5001_sm3 = {
+    0x1100, 5, 0x20,
+    {&el5001_st, &el5001_ip, NULL}
+};
+
+const ec_slave_type_t Beckhoff_EL5001 = {
+    "Beckhoff", "EL5001", "SSI-Interface", EC_MAILBOX_SLAVE,
+    {&mailbox_sm0, &mailbox_sm1, &el5001_sm2, &el5001_sm3, NULL}
+};
+
+/*****************************************************************************/
+
+const ec_field_t el5101_ct = {ec_control, 1};
+const ec_field_t el5101_op = {ec_opvalue, 2};
+const ec_field_t el5101_st = {ec_status,  1};
+const ec_field_t el5101_ip = {ec_ipvalue, 2};
+const ec_field_t el5101_la = {ec_ipvalue, 2};
+
+const ec_sync_t el5101_sm2 = {
+    0x1000, 3, 0x24,
+    {&el5101_ct, &el5101_op, NULL}
+};
+
+const ec_sync_t el5101_sm3 = {
+    0x1100, 5, 0x20,
+    {&el5101_st, &el5101_ip, &el5101_la, NULL}
+};
+
+const ec_slave_type_t Beckhoff_EL5101 =
 {
-    "Beckhoff", "EL5101", "Incremental Encoder Interface",
-    EC_MAILBOX_SLAVE, sm0_multi, sm1_multi, sm2_5101, sm3_5101, fmmu0_5101, 5
+    "Beckhoff", "EL5101", "Incremental Encoder Interface", EC_MAILBOX_SLAVE,
+    {&mailbox_sm0, &mailbox_sm1, &el5101_sm2, &el5101_sm3, NULL}
 };
 
 /*****************************************************************************/
@@ -167,10 +181,14 @@
     {0x00000002, 0x10063052, &Beckhoff_EL4102},
     {0x00000002, 0x10243052, &Beckhoff_EL4132},
     {0x00000002, 0x13893052, &Beckhoff_EL5001},
-    {0x00000002, 0x13ED3052, &Beckhoff_EL5101}
+    {0x00000002, 0x13ED3052, &Beckhoff_EL5101},
+    {}
 };
 
-unsigned int slave_ident_count = sizeof(slave_idents)
-     / sizeof(ec_slave_ident_t);
+/*****************************************************************************/
 
-/*****************************************************************************/
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:4 ***
+;;; End: ***
+*/
--- a/master/types.h	Wed Feb 22 17:36:28 2006 +0000
+++ b/master/types.h	Thu Feb 23 09:58:50 2006 +0000
@@ -11,10 +11,17 @@
 #ifndef _EC_TYPES_H_
 #define _EC_TYPES_H_
 
+#include <linux/types.h>
+
 #include "../include/EtherCAT_rt.h"
 
 /*****************************************************************************/
 
+#define EC_MAX_FIELDS 10
+#define EC_MAX_SYNC   16
+
+/*****************************************************************************/
+
 /**
    Features eines EtherCAT-Slaves.
 
@@ -32,6 +39,34 @@
 /*****************************************************************************/
 
 /**
+   Prozessdatenfeld.
+*/
+
+typedef struct
+{
+    ec_field_type_t type;
+    unsigned int size;
+}
+ec_field_t;
+
+/*****************************************************************************/
+
+/**
+   Sync-Manager.
+*/
+
+typedef struct
+{
+    uint16_t physical_start_address;
+    uint16_t size;
+    uint8_t control_byte;
+    const ec_field_t *fields[EC_MAX_FIELDS];
+}
+ec_sync_t;
+
+/*****************************************************************************/
+
+/**
    Beschreibung eines EtherCAT-Slave-Typs.
 
    Diese Beschreibung dient zur Konfiguration einer bestimmten
@@ -39,28 +74,16 @@
    Slave-internen Sync-Manager und FMMU's.
 */
 
-struct ec_slave_type
+typedef struct ec_slave_type
 {
     const char *vendor_name; /**< Name des Herstellers */
     const char *product_name; /**< Name des Slaves-Typs */
-    const char *product_desc; /**< Genauere Beschreibung des Slave-Typs */
-
+    const char *description; /**< Genauere Beschreibung des Slave-Typs */
     ec_slave_features_t features; /**< Features des Slave-Typs */
-
-    const unsigned char *sm0; /**< Konfigurationsdaten des
-                                 ersten Sync-Managers */
-    const unsigned char *sm1; /**< Konfigurationsdaten des
-                                 zweiten Sync-Managers */
-    const unsigned char *sm2; /**< Konfigurationsdaten des
-                                 dritten Sync-Managers */
-    const unsigned char *sm3; /**< Konfigurationsdaten des
-                                 vierten Sync-Managers */
-
-    const unsigned char *fmmu0; /**< Konfigurationsdaten
-                                   der ersten FMMU */
-
-    unsigned int process_data_size; /**< Länge der Prozessdaten in Bytes */
-};
+    const ec_sync_t *sync_managers[EC_MAX_SYNC]; /**< Sync-Manager
+                                                    Konfigurationen */
+}
+ec_slave_type_t;
 
 /*****************************************************************************/
 
@@ -81,9 +104,13 @@
 
 extern ec_slave_ident_t slave_idents[]; /**< Statisches Array der
                                            Slave-Identifikationen */
-extern unsigned int slave_ident_count; /**< Anzahl der vorhandenen
-                                          Slave-Identifikationen */
 
 /*****************************************************************************/
 
 #endif
+
+/* Emacs-Konfiguration
+;;; Local Variables: ***
+;;; c-basic-offset:4 ***
+;;; End: ***
+*/
--- a/mini/mini.c	Wed Feb 22 17:36:28 2006 +0000
+++ b/mini/mini.c	Thu Feb 23 09:58:50 2006 +0000
@@ -17,48 +17,51 @@
 
 /*****************************************************************************/
 
-ec_master_t *master = NULL;
-ec_slave_t *s_in, *s_out, *s_ssi;
+#define ABTASTFREQUENZ 1000
 
 struct timer_list timer;
 
-ec_slave_init_t slaves[] = {
-    // Zeiger, Index, Herstellername, Produktname, Domäne
-    {  &s_in,  "1",   "Beckhoff",     "EL3102",    1      },
-    {  &s_out, "2",   "Beckhoff",     "EL2004",    1      },
-    {  &s_ssi, "3",   "Beckhoff",     "EL5001",    1      }
+/*****************************************************************************/
+
+// EtherCAT
+ec_master_t *master = NULL;
+ec_domain_t *domain1 = NULL;
+
+// Prozessdaten
+uint8_t *dig_out1;
+uint16_t *ssi_value;
+uint16_t *inc_value;
+
+uint32_t angle0;
+
+ec_field_init_t domain1_fields[] = {
+    {(void **) &dig_out1,    "2", "Beckhoff", "EL2004", ec_opvalue, 0, 1},
+    {(void **) &ssi_value,   "3", "Beckhoff", "EL5001", ec_ipvalue, 0, 1},
+    {(void **) &inc_value, "0:4", "Beckhoff", "EL5101", ec_ipvalue, 0, 1},
+    {}
 };
 
-#define SLAVE_COUNT (sizeof(slaves) / sizeof(ec_slave_init_t))
-
 /*****************************************************************************/
 
 void run(unsigned long data)
 {
-    static unsigned int counter;
-
-    // Klemmen-IO
-    EC_WRITE_EL20XX(s_out, 3, EC_READ_EL31XX(s_in, 0) < 0);
-
-    if (!counter) {
-        EtherCAT_rt_debug_level(master, 2);
-    }
+    static unsigned int counter = 0;
 
     // Prozessdaten lesen und schreiben
-    EtherCAT_rt_domain_xio(master, 1, 100);
+    EtherCAT_rt_domain_xio(domain1);
+
+    angle0 = (uint32_t) *inc_value;
 
     if (counter) {
         counter--;
     }
     else {
-        EtherCAT_rt_debug_level(master, 0);
-        printk("SSI status=%X value=%u\n",
-               EC_READ_EL5001_STATE(s_ssi), EC_READ_EL5001_VALUE(s_ssi));
-        counter = 1000;
+        counter = ABTASTFREQUENZ;
+        printk(KERN_INFO "angle0 = %i\n", angle0);
     }
 
     // Timer neu starten
-    timer.expires += HZ / 1000;
+    timer.expires += HZ / ABTASTFREQUENZ;
     add_timer(&timer);
 }
 
@@ -66,41 +69,52 @@
 
 int __init init_mini_module(void)
 {
+    const ec_field_init_t *field;
+
     printk(KERN_INFO "=== Starting Minimal EtherCAT environment... ===\n");
 
     if ((master = EtherCAT_rt_request_master(0)) == NULL) {
-        printk(KERN_ERR "EtherCAT master 0 not available!\n");
+        printk(KERN_ERR "Error requesting master 0!\n");
         goto out_return;
     }
 
-    if (EtherCAT_rt_register_slave_list(master, slaves, SLAVE_COUNT)) {
-        printk(KERN_ERR "Could not register slaves!\n");
+    EtherCAT_rt_master_print(master);
+
+    printk(KERN_INFO "Registering domain...\n");
+
+    if (!(domain1 = EtherCAT_rt_master_register_domain(master, ec_sync, 100)))
+    {
+        printk(KERN_ERR "EtherCAT: Could not register domain!\n");
         goto out_release_master;
     }
 
-    printk("Activating all EtherCAT slaves.\n");
+    printk(KERN_INFO "Registering domain fields...\n");
 
-    if (EtherCAT_rt_activate_slaves(master)) {
-        printk(KERN_ERR "EtherCAT: Could not activate slaves!\n");
-        goto out_release_master;
+    for (field = domain1_fields; field->data; field++)
+    {
+        if (!EtherCAT_rt_register_slave_field(domain1,
+                                              field->address,
+                                              field->vendor,
+                                              field->product,
+                                              field->data,
+                                              field->field_type,
+                                              field->field_index,
+                                              field->field_count)) {
+            printk(KERN_ERR "EtherCAT: Could not register field!\n");
+            goto out_release_master;
+        }
     }
 
-    printk("Configuring EtherCAT slaves.\n");
+    printk(KERN_INFO "Activating master...\n");
 
-    if (EtherCAT_rt_canopen_sdo_write(master, s_ssi, 0x4067, 0, 2, 2)) {
-        printk(KERN_ERR "EtherCAT: Could not set SSI baud rate!\n");
-        goto out_release_master;
-    }
-
-    if (EtherCAT_rt_canopen_sdo_write(master, s_ssi, 0x4061, 4, 1, 1)) {
-        printk(KERN_ERR "EtherCAT: Could not set SSI feature bit!\n");
+    if (EtherCAT_rt_master_activate(master)) {
+        printk(KERN_ERR "EtherCAT: Could not activate master!\n");
         goto out_release_master;
     }
 
     printk("Starting cyclic sample thread.\n");
 
     init_timer(&timer);
-
     timer.function = run;
     timer.expires = jiffies + 10; // Das erste Mal sofort feuern
     add_timer(&timer);
@@ -126,9 +140,9 @@
     {
         del_timer_sync(&timer);
 
-        printk(KERN_INFO "Deactivating slaves.\n");
+        printk(KERN_INFO "Deactivating master...\n");
 
-        EtherCAT_rt_deactivate_slaves(master);
+        EtherCAT_rt_master_deactivate(master);
         EtherCAT_rt_release_master(master);
     }
 
@@ -139,7 +153,7 @@
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR ("Florian Pose <fp@igh-essen.com>");
-MODULE_DESCRIPTION ("Minimal EtherCAT environment");
+MODULE_DESCRIPTION ("EtherCAT minimal test environment");
 
 module_init(init_mini_module);
 module_exit(cleanup_mini_module);
--- a/rt/Makefile	Wed Feb 22 17:36:28 2006 +0000
+++ b/rt/Makefile	Thu Feb 23 09:58:50 2006 +0000
@@ -14,7 +14,6 @@
 obj-m := msr_modul.o
 
 msr_modul-objs := msr_module.o \
-		msr_jitter.o \
 		rt_lib/msr-core/msr_lists.o \
 		rt_lib/msr-core/msr_main.o \
 		rt_lib/msr-core/msr_charbuf.o \
@@ -24,7 +23,9 @@
 		rt_lib/msr-core/msr_proc.o \
 		rt_lib/msr-core/msr_error_reg.o \
 		rt_lib/msr-utils/msr_utils.o \
+		rt_lib/msr-utils/msr_time.o \
 		rt_lib/msr-math/msr_base64.o \
+		rt_lib/msr-math/msr_hex_bin.o \
 		libm.o
 
 EXTRA_CFLAGS := -I $(src)/rt_lib/msr-include -D_SIMULATION \
--- a/rt/msr_jitter.c	Wed Feb 22 17:36:28 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/******************************************************************************
- *
- * msr_jitter.c
- *
- * 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__
-#endif
-#ifndef MODULE
-#  define MODULE
-#endif
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <asm/msr.h> /* maschine-specific registers */
-#include <linux/param.h> /* fuer HZ */
-
-#include <msr_reg.h>
-#include "msr_jitter.h"
-
-/*--includes-----------------------------------------------------------------*/
-
-/*--external functions-------------------------------------------------------*/
-
-/*--external data------------------------------------------------------------*/
-
-/*--public data--------------------------------------------------------------*/
-
-/*--local data---------------------------------------------------------------*/
-
-#define NUMCLASSES 16
-
-static int jittime[NUMCLASSES]={0,1,2,5,10,20,50,100,200,500,
-                                1000,2000,5000,10000,20000,50000}; //in usec
-static int jitcount[NUMCLASSES];
-static double jitpercent[NUMCLASSES];
-static unsigned int tcount = 1;
-
-static void msr_jit_read(void)
-{
-    int i;
-    for(i=0;i<NUMCLASSES;i++) {
-	if(tcount >100) {
-	    jitpercent[i] = jitcount[i]*100.0/tcount;
-	}
-    }
-}
-
-void msr_jitter_init(void)
-{
-    msr_reg_int_list("/Taskinfo/Jitter/Classes","usec",
-                     &jittime[0],MSR_R,NUMCLASSES,NULL,NULL,NULL);
-    msr_reg_int_list("/Taskinfo/Jitter/Count","",
-                     &jitcount[0],MSR_R,NUMCLASSES,NULL,NULL,NULL);
-    msr_reg_dbl_list("/Taskinfo/Jitter/percent","%",
-                     &jitpercent[0],MSR_R,NUMCLASSES,NULL,NULL,&msr_jit_read);
-}
-
-/******************************************************************************
- *
- * Function: msr_jitter_run
- *
- * Beschreibung:
- *
- *
- * Parameter: Zeiger auf msr_data
- *
- * Rückgabe:
- *
- * Status: exp
- *
- *****************************************************************************/
-
-void msr_jitter_run(unsigned int hz) {
-
-    int i,hit;
-    static int firstrun = 1;
-    static unsigned long k,j = 0;
-    unsigned int dt,jitter;
-
-
-    rdtscl(k);
-
-    tcount++;
-
-    //Zeitabstand zwischen zwei Interrupts in usec
-
-    dt = ((unsigned long)(100000/HZ)*((unsigned long)(k-j)))
-        /(current_cpu_data.loops_per_jiffy/10);
-
-    jitter = (unsigned int)abs((int)dt-(int)1000000/hz);
-    //jitter errechnet zum Sollabtastrate
-
-    //in die Klassen einsortieren
-    if(!firstrun) { //das erste mal nicht einsortieren
-	hit = 0;
-	for(i=0;i<NUMCLASSES-1;i++) {
-	    if(jitter>=jittime[i] && jitter<jittime[i+1]) {
-		jitcount[i]++;
-		hit = 1;
-		break;
-	    }
-	}
-	if(hit == 0) //grŽöŽßer als der letzte
-	    jitcount[NUMCLASSES-1]++;
-
-    }
-    else
-	firstrun = 0;
-
-    j = k;
-
-
-}
--- a/rt/msr_jitter.h	Wed Feb 22 17:36:28 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/******************************************************************************
- *
- * msr_jitter.c
- *
- * 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$
- *
- *****************************************************************************/
-
-/*--Schutz vor mehrfachem includieren----------------------------------------*/
-
-#ifndef _MSR_JITTER_H_
-#define _MSR_JITTER_H_
-
-void msr_jitter_run(unsigned int hz);
-void msr_jitter_init(void);
-
-#endif
--- a/rt/msr_module.c	Wed Feb 22 17:36:28 2006 +0000
+++ b/rt/msr_module.c	Thu Feb 23 09:58:50 2006 +0000
@@ -21,6 +21,8 @@
 // Linux
 #include <linux/module.h>
 #include <linux/ipipe.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 // RT_lib
 #include <msr_main.h>
@@ -28,105 +30,62 @@
 #include <msr_messages.h>
 #include <msr_float.h>
 #include <msr_reg.h>
+#include <msr_time.h>
 #include "msr_param.h"
-#include "msr_jitter.h"
 
 // EtherCAT
 #include "../include/EtherCAT_rt.h"
 #include "../include/EtherCAT_si.h"
 
 // Defines/Makros
-#define TSC2US(T1, T2) ((T2 - T1) * 1000UL / cpu_khz)
 #define HZREDUCTION (MSR_ABTASTFREQUENZ / HZ)
 
 /*****************************************************************************/
 /* Globale Variablen */
 
-// RT_lib
-extern struct timeval process_time;
-struct timeval msr_time_increment; // Increment per Interrupt
-
 // Adeos
 static struct ipipe_domain this_domain;
 static struct ipipe_sysinfo sys_info;
 
 // EtherCAT
 ec_master_t *master = NULL;
-ec_slave_t *s_in1, *s_out1, *s_ssi, *s_inc;
-
-uint16_t angle0;
-
-ec_slave_init_t slaves[] = {
-    {&s_in1,  "1", "Beckhoff", "EL3102", 0},
-    {&s_out1, "2", "Beckhoff", "EL2004", 0},
-    {&s_ssi,  "3", "Beckhoff", "EL5001", 0},
-    {&s_inc,  "0:4", "Beckhoff", "EL5101", 0}
+ec_domain_t *domain1 = NULL;
+
+// Prozessdaten
+uint8_t *dig_out1;
+uint16_t *ssi_value;
+uint16_t *inc_value;
+
+uint32_t angle0;
+
+ec_field_init_t domain1_fields[] = {
+    {(void **) &dig_out1,    "2", "Beckhoff", "EL2004", ec_opvalue, 0, 1},
+    {(void **) &ssi_value,   "3", "Beckhoff", "EL5001", ec_ipvalue, 0, 1},
+    {(void **) &inc_value, "0:4", "Beckhoff", "EL5101", ec_ipvalue, 0, 1},
+    {}
 };
 
-#define SLAVE_COUNT (sizeof(slaves) / sizeof(ec_slave_init_t))
-
-/******************************************************************************
- *
- * Function: msr_controller_run()
- *
- *****************************************************************************/
+/*****************************************************************************/
 
 static void msr_controller_run(void)
 {
-    static unsigned int counter = 0;
-
-    msr_jitter_run(MSR_ABTASTFREQUENZ);
-
-    EC_WRITE_EL20XX(s_out1, 3, EC_READ_EL31XX(s_in1, 0) < 0);
-
-    if (!counter) {
-        EtherCAT_rt_debug_level(master, 2);
-    }
-
     // Prozessdaten lesen und schreiben
-    EtherCAT_rt_domain_xio(master, 0, 40);
-
-    if (counter) {
-        counter--;
-    }
-    else {
-        EtherCAT_rt_debug_level(master, 0);
-        printk("SSI status=0x%X value=%u\n",
-               EC_READ_EL5001_STATE(s_ssi), EC_READ_EL5001_VALUE(s_ssi));
-        printk("INC status=0x%X value=%u\n",
-               EC_READ_EL5101_STATE(s_inc), EC_READ_EL5101_VALUE(s_inc));
-
-        counter = MSR_ABTASTFREQUENZ * 5;
-    }
-
-    angle0 = EC_READ_EL5101_VALUE(s_inc);
-}
-
-/******************************************************************************
- *
- *  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
- *
- *****************************************************************************/
+    EtherCAT_rt_domain_xio(domain1);
+
+    angle0 = (uint32_t) *inc_value;
+}
+
+/*****************************************************************************/
 
 void msr_run(unsigned irq)
 {
     static int counter = 0;
 
-    timeval_add(&process_time, &process_time, &msr_time_increment);
     MSR_ADEOS_INTERRUPT_CODE(msr_controller_run(); msr_write_kanal_list(););
 
-    ipipe_control_irq(irq,0,IPIPE_ENABLE_MASK);  //Interrupt bestŽätigen
-    if (counter++ > HZREDUCTION) {
-	ipipe_propagate_irq(irq);  //und weiterreichen
+    ipipe_control_irq(irq, 0, IPIPE_ENABLE_MASK); // Interrupt bestŽätigen
+    if (++counter >= HZREDUCTION) {
+	ipipe_propagate_irq(irq);  // und weiterreichen
 	counter = 0;
     }
 }
@@ -144,75 +103,78 @@
     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)
 {
-    //msr_reg_kanal("/value", "V", &value, TDBL);
-    //msr_reg_kanal("/dig1", "", &dig1, TINT);
-    msr_reg_kanal("/angle0", "", &angle0, TINT);
+    msr_reg_kanal("/angle0", "", &angle0, TUINT);
 
     return 0;
 }
 
-/******************************************************************************
- * the init/clean material
- *****************************************************************************/
+/*****************************************************************************/
 
 int __init init_rt_module(void)
 {
     struct ipipe_domain_attr attr; //ipipe
+    const ec_field_init_t *field;
 
     // Als allererstes die RT-lib initialisieren
-    if (msr_rtlib_init(1,MSR_ABTASTFREQUENZ,10,&msr_globals_register) < 0) {
+    if (msr_rtlib_init(1, MSR_ABTASTFREQUENZ, 10, &msr_globals_register) < 0) {
         msr_print_warn("msr_modul: can't initialize rtlib!");
         goto out_return;
     }
 
-    msr_jitter_init();
-
-    printk(KERN_INFO "=== Starting EtherCAT environment... ===\n");
-
     if ((master = EtherCAT_rt_request_master(0)) == NULL) {
         printk(KERN_ERR "Error requesting master 0!\n");
         goto out_msr_cleanup;
     }
 
-    if (EtherCAT_rt_register_slave_list(master, slaves, SLAVE_COUNT)) {
-        printk(KERN_ERR "EtherCAT: Could not register slaves!\n");
-        goto out_release_master;
-    }
-
-    if (EtherCAT_rt_activate_slaves(master) < 0) {
-        printk(KERN_ERR "EtherCAT: Could not activate slaves!\n");
-        goto out_release_master;
-    }
-
-    if (EtherCAT_rt_canopen_sdo_write(master, s_ssi, 0x4067, 0, 1, 2)) {
+    EtherCAT_rt_master_print(master);
+
+    printk(KERN_INFO "Registering domain...\n");
+
+    if (!(domain1 = EtherCAT_rt_master_register_domain(master, ec_sync, 100)))
+    {
+        printk(KERN_ERR "EtherCAT: Could not register domain!\n");
+        goto out_release_master;
+    }
+
+    printk(KERN_INFO "Registering domain fields...\n");
+
+    for (field = domain1_fields; field->data; field++)
+    {
+        if (!EtherCAT_rt_register_slave_field(domain1,
+                                              field->address,
+                                              field->vendor,
+                                              field->product,
+                                              field->data,
+                                              field->field_type,
+                                              field->field_index,
+                                              field->field_count)) {
+            printk(KERN_ERR "EtherCAT: Could not register field!\n");
+            goto out_release_master;
+        }
+    }
+
+    printk(KERN_INFO "Activating master...\n");
+
+    if (EtherCAT_rt_master_activate(master)) {
+        printk(KERN_ERR "EtherCAT: Could not activate master!\n");
+        goto out_release_master;
+    }
+
+#if 0
+    if (EtherCAT_rt_canopen_sdo_write(master, "0:4", 0x4067, 0, 1, 2)) {
         printk(KERN_ERR "EtherCAT: Could not set SSI baud rate!\n");
         goto out_release_master;
     }
 
-    if (EtherCAT_rt_canopen_sdo_write(master, s_ssi, 0x4061, 4, 1, 1)) {
+    if (EtherCAT_rt_canopen_sdo_write(master, "0:4", 0x4061, 4, 1, 1)) {
         printk(KERN_ERR "EtherCAT: Could not set SSI feature bit!\n");
         goto out_release_master;
     }
-
-    do_gettimeofday(&process_time);
-    msr_time_increment.tv_sec = 0;
-    msr_time_increment.tv_usec = (unsigned int) (1000000 / MSR_ABTASTFREQUENZ);
+#endif
 
     ipipe_init_attr(&attr);
     attr.name = "IPIPE-MSR-MODULE";
@@ -245,10 +207,10 @@
     {
         printk(KERN_INFO "=== Stopping EtherCAT environment... ===\n");
 
-        printk(KERN_INFO "Deactivating slaves.\n");
-
-        if (EtherCAT_rt_deactivate_slaves(master) < 0) {
-          printk(KERN_WARNING "Warning - Could not deactivate slaves!\n");
+        printk(KERN_INFO "Deactivating master...\n");
+
+        if (EtherCAT_rt_master_deactivate(master) < 0) {
+          printk(KERN_WARNING "Warning - Could not deactivate master!\n");
         }
 
         EtherCAT_rt_release_master(master);
@@ -262,8 +224,8 @@
 /*****************************************************************************/
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR ("Wilhelm Hagemeister <hm@igh-essen.com>");
-MODULE_DESCRIPTION ("EtherCAT test environment");
+MODULE_AUTHOR ("Florian Pose <fp@igh-essen.com>");
+MODULE_DESCRIPTION ("EtherCAT real-time test environment");
 
 module_init(init_rt_module);
 module_exit(cleanup_rt_module);