Store sync manager configurations in ec_slave_config_t instead of Pdo
authorFlorian Pose <fp@igh-essen.com>
Thu, 26 Jun 2008 13:16:15 +0000
changeset 1055 2be8918682fa
parent 1054 4c16fe64b403
child 1056 7b656881e771
Store sync manager configurations in ec_slave_config_t instead of Pdo
lists for each direction; changed realtime interface to allow sync
manager configuration.
include/ecrt.h
master/Kbuild.in
master/Makefile.am
master/cdev.c
master/domain.c
master/fmmu_config.c
master/fmmu_config.h
master/fsm_coe_map.c
master/fsm_coe_map.h
master/fsm_pdo_assign.c
master/fsm_pdo_assign.h
master/fsm_pdo_mapping.c
master/fsm_slave_config.c
master/fsm_slave_scan.c
master/globals.h
master/ioctl.h
master/master.c
master/pdo.c
master/pdo.h
master/pdo_list.c
master/pdo_list.h
master/sdo_request.c
master/slave.c
master/slave.h
master/slave_config.c
master/slave_config.h
master/sync.c
master/sync.h
master/sync_config.c
master/sync_config.h
tools/Master.cpp
tools/Master.h
--- a/include/ecrt.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/include/ecrt.h	Thu Jun 26 13:16:15 2008 +0000
@@ -220,44 +220,63 @@
 /** Direction type for Pdo assignment functions.
  */
 typedef enum {
+    EC_DIR_INVALID, /**< Invalid direction. Do not use this value. */
     EC_DIR_OUTPUT, /**< Values written by the master. */
-    EC_DIR_INPUT   /**< Values read by the master. */
+    EC_DIR_INPUT, /**< Values read by the master. */
+    EC_DIR_COUNT /**< Number of directions. For internal use only. */
 } ec_direction_t;
 
 /*****************************************************************************/
 
-/** Pdo entry information.
- *
- * This can be used to map multiple Pdo entries into a given Pdo using
- * ecrt_slave_config_pdos().
+/** Pdo entry configuration information.
+ *
+ * This is the data type of the \a entries field in ec_pdo_info_t.
+ *
+ * \see ecrt_slave_config_sync_managers().
  */
 typedef struct {
-    uint16_t index; /**< Index of the Pdo entry to add to the Pdo
-                            mapping. */
-    uint8_t subindex; /**< Subindex of the Pdo entry. */
+    uint16_t index; /**< Pdo entry index. */
+    uint8_t subindex; /**< Pdo entry subindex. */
     uint8_t bit_length; /**< Size of the Pdo entry in bit. */
 } ec_pdo_entry_info_t;
 
 /*****************************************************************************/
 
-/** Pdo information.
- *
- * This can be use to assign multiple Pdos to a sync manager using
- * ecrt_slave_config_pdos().
+/** Pdo configuration information.
+ * 
+ * This is the data type of the \a pdos field in ec_sync_info_t.
+ * 
+ * \see ecrt_slave_config_sync_managers().
  */
 typedef struct {
-    ec_direction_t dir; /**< Pdo direction (input/output). */
-    uint16_t index; /**< Index of the Pdo to assign. */
-    unsigned int n_entries; /**< Number of Pdo entries in \a entries to map.
+    uint16_t index; /**< Pdo index. */
+    uint8_t n_entries; /**< Number of Pdo entries in \a entries to map.
                               Zero means, that the default mapping shall be
                               used (this can only be done if the slave is
                               present at bus configuration time). */
-    ec_pdo_entry_info_t *entries; /**< Array of Pdo entries to map. This must
-                                    contain at least \a n_entries values. */
+    ec_pdo_entry_info_t *entries; /**< Array of Pdo entries to map. Can either
+                                    be \a NULL, or must contain at
+                                    least \a n_entries values. */
 } ec_pdo_info_t;
 
 /*****************************************************************************/
 
+/** Sync manager configuration information.
+ *
+ * This can be use to configure multiple sync managers including the Pdo
+ * assignment and Pdo mapping. It is used as an input parameter type in
+ * ecrt_slave_config_sync_managers().
+ */
+typedef struct {
+    uint8_t index; /**< Sync manager index. */
+    ec_direction_t dir; /**< Sync manager direction. */
+    uint16_t n_pdos; /**< Number of Pdos in \a pdos. */
+    ec_pdo_info_t *pdos; /**< Array with Pdos to assign. This must contain
+                            at least \a n_pdos Pdos. */
+} ec_sync_info_t;
+
+/*****************************************************************************/
+
 /** List record type for Pdo entry mass-registration.
  *
  * This type is used for the array parameter of the
@@ -426,30 +445,46 @@
  * Slave configuration methods
  *****************************************************************************/
 
+/** Configure a sync manager.
+ *
+ * Sets the direction of a sync manager. The direction bits from the default
+ * control register from SII will be overriden, when this function is called.
+ *
+ * \return zero on success, else non-zero
+ */
+int ecrt_slave_config_sync_manager(
+        ec_slave_config_t *sc, /**< Slave configuration. */
+        uint8_t sync_index, /**< Sync manager index. */
+        ec_direction_t dir /**< Input/Output. */
+        );
+
 /** Add a Pdo to a sync manager's Pdo assignment.
  *
- * \see ecrt_slave_config_pdos()
+ * \see ecrt_slave_config_sync_managers()
  * \return zero on success, else non-zero
  */
 int ecrt_slave_config_pdo_assign_add(
         ec_slave_config_t *sc, /**< Slave configuration. */
-        ec_direction_t dir, /**< Sync manager direction (input/output). */
+        uint8_t sync_index, /**< Sync manager index. */
         uint16_t index /**< Index of the Pdo to assign. */
         );
 
 /** Clear a sync manager's Pdo assignment.
  *
  * This can be called before assigning Pdos via
- * ecrt_slave_config_pdo_assign_add(), to clear the default assignment.
+ * ecrt_slave_config_pdo_assign_add(), to clear the default assignment of a
+ * sync manager.
+ * 
+ * \see ecrt_slave_config_sync_managers()
  */
 void ecrt_slave_config_pdo_assign_clear(
         ec_slave_config_t *sc, /**< Slave configuration. */
-        ec_direction_t dir /**< Sync manager direction (input/output). */
+        uint8_t sync_index /**< Sync manager index. */
         );
 
 /** Add a Pdo entry to the given Pdo's mapping.
  *
- * \see ecrt_slave_config_pdos()
+ * \see ecrt_slave_config_sync_managers()
  * \return zero on success, else non-zero
  */
 int ecrt_slave_config_pdo_mapping_add(
@@ -466,21 +501,23 @@
  *
  * This can be called before mapping Pdo entries via
  * ecrt_slave_config_pdo_mapping_add(), to clear the default mapping.
+ *
+ * \see ecrt_slave_config_sync_managers()
  */
 void ecrt_slave_config_pdo_mapping_clear(
         ec_slave_config_t *sc, /**< Slave configuration. */
         uint16_t pdo_index /**< Index of the Pdo. */
         );
 
-/** Specify the Pdo assignment and (optionally) the Pdo mappings.
+/** Specify a complete Pdo configuration.
  *
  * This function is a convenience wrapper for the functions
- * ecrt_slave_config_pdo_assign_clear(), ecrt_slave_config_pdo_assign_add(),
- * ecrt_slave_config_pdo_mapping_clear() and
- * ecrt_slave_config_pdo_mapping_add(), that are better suitable for automatic
- * code generation.
- *
- * The following example shows, how to specify a complete Pdo assignment
+ * ecrt_slave_config_sync_manager(), ecrt_slave_config_pdo_assign_clear(),
+ * ecrt_slave_config_pdo_assign_add(), ecrt_slave_config_pdo_mapping_clear()
+ * and ecrt_slave_config_pdo_mapping_add(), that are better suitable for
+ * automatic code generation.
+ *
+ * The following example shows, how to specify a complete configuration,
  * including the Pdo mappings. With this information, the master is able to
  * reserve the complete process data, even if the slave is not present at
  * configuration time:
@@ -497,41 +534,51 @@
  * };
  * 
  * const ec_pdo_info_t el3162_pdos[] = {
- *     {EC_DIR_INPUT, 0x1A00, 2, el3162_channel1},
- *     {EC_DIR_INPUT, 0x1A01, 2, el3162_channel2},
+ *     {0x1A00, 2, el3162_channel1},
+ *     {0x1A01, 2, el3162_channel2},
  * };
  * 
- * if (ecrt_slave_config_pdos(sc, 2, el3162_pdos))
+ * const ec_pdo_info_t el3162_syncs[] = {
+ *     {2, EC_DIR_INPUT, 2, el3162_el3162_pdos},
+ * };
+ * 
+ * if (ecrt_slave_config_syncs(sc, 1, el3162_syncs))
  *     return -1; // error
  * \endcode
  * 
- * The next example shows, how to configure only the Pdo assignment. The
+ * The next example shows, how to configure the Pdo assignment only. The
  * entries for each assigned Pdo are taken from the Pdo's default mapping.
  * Please note, that Pdo entry registration will fail, if the Pdo
  * configuration is left empty and the slave is offline.
  *
  * \code
  * const ec_pdo_info_t pdos[] = {
- *     {EC_DIR_INPUT, 0x1600}, // Channel 1
- *     {EC_DIR_INPUT, 0x1601}  // Channel 2
+ *     {0x1600}, // Channel 1
+ *     {0x1601}  // Channel 2
  * };
  * 
- * if (ecrt_slave_config_pdos(slave_config_ana_in, 2, pdos))
+ * const ec_sync_info_t syncs[] = {
+ *     {2, EC_DIR_INPUT, 2, pdos},
+ * };
+ * 
+ * if (ecrt_slave_config_pdos(slave_config_ana_in, 2, syncs))
  *     return -1; // error
  * \endcode
  *
- * Processing of \a pdo_infos will stop, if
- * - the number of processed items reaches \a n_infos, or
- * - the \a dir member of an ec_pdo_info_t item is EC_END. In this case,
- *   \a n_infos should set to a number greater than the number of list items;
+ * Processing of \a syncs will stop, if
+ * - the number of processed items reaches \a n_syncs, or
+ * - the \a index member of an ec_sync_info_t item is 0xff. In this case,
+ *   \a n_syncs should set to a number greater than the number of list items;
  *   using EC_END is recommended.
  *
  * \return zero on success, else non-zero
  */
-int ecrt_slave_config_pdos(
+int ecrt_slave_config_sync_managers(
         ec_slave_config_t *sc, /**< Slave configuration. */
-        unsigned int n_infos, /**< Number of Pdo infos in \a pdo_infos. */
-        const ec_pdo_info_t pdo_infos[] /**< List with Pdos. */
+        unsigned int n_syncs, /**< Number of sync manager configurations in
+                                \a syncs. */
+        const ec_sync_info_t syncs[] /**< Array of sync manager
+                                       configurations. */
         );
 
 /** Registers a Pdo entry for process data exchange in a domain.
--- a/master/Kbuild.in	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/Kbuild.in	Thu Jun 26 13:16:15 2008 +0000
@@ -61,7 +61,8 @@
     sdo_request.o \
     slave.o \
     slave_config.o \
-    sync.o
+    sync.o \
+	sync_config.o
 
 ifeq (@ENABLE_EOE@,1)
 	ec_master-objs += ethernet.o
--- a/master/Makefile.am	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/Makefile.am	Thu Jun 26 13:16:15 2008 +0000
@@ -63,7 +63,8 @@
 	sdo_request.c sdo_request.h \
 	slave.c slave.h \
 	slave_config.c slave_config.h \
-	sync.c sync.h
+	sync.c sync.h \
+	sync_config.c sync_config.h
 
 modules:
 	$(MAKE) -C "@abs_top_srcdir@" modules
--- a/master/cdev.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/cdev.c	Thu Jun 26 13:16:15 2008 +0000
@@ -243,7 +243,7 @@
                 sync = &slave->sii.syncs[data.sync_index];
 
                 data.physical_start_address = sync->physical_start_address;
-                data.default_size = sync->length;
+                data.default_size = sync->default_length;
                 data.control_register = sync->control_register;
                 data.enable = sync->enable;
                 data.assign_source = sync->assign_source;
@@ -290,7 +290,6 @@
                     break;
                 }
 
-                data.dir = pdo->dir;
                 data.index = pdo->index;
                 data.entry_count = ec_pdo_entry_count(pdo);
 
@@ -420,7 +419,8 @@
 
                 data.slave_config_alias = fmmu->sc->alias;
                 data.slave_config_position = fmmu->sc->position;
-                data.fmmu_dir = fmmu->dir;
+                data.sync_index = fmmu->sync_index;
+                data.dir = fmmu->dir;
                 data.logical_address = fmmu->logical_start_address;
                 data.data_size = fmmu->data_size;
 
@@ -832,6 +832,7 @@
             {
                 ec_ioctl_config_t data;
                 const ec_slave_config_t *sc;
+                uint8_t i;
 
                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
                     retval = -EFAULT;
@@ -850,10 +851,11 @@
                 data.position = sc->position;
                 data.vendor_id = sc->vendor_id;
                 data.product_code = sc->product_code;
-                data.pdo_count[EC_DIR_OUTPUT] =
-                    ec_pdo_list_count(&sc->pdos[EC_DIR_OUTPUT]);
-                data.pdo_count[EC_DIR_INPUT] =
-                    ec_pdo_list_count(&sc->pdos[EC_DIR_INPUT]);
+                for (i = 0; i < EC_MAX_SYNCS; i++) {
+                    data.syncs[i].dir = sc->sync_configs[i].dir;
+                    data.syncs[i].pdo_count =
+                        ec_pdo_list_count(&sc->sync_configs[i].pdos);
+                }
                 data.sdo_count = ec_slave_config_sdo_count(sc);
                 data.attached = sc->slave != NULL;
 
@@ -881,14 +883,16 @@
                     break;
                 }
 
-                if (data.direction > EC_DIR_INPUT) {
-                    EC_ERR("Invalid direction %u!\n", data.direction);
+                if (data.sync_index >= EC_MAX_SYNCS) {
+                    EC_ERR("Invalid sync manager index %u!\n",
+                            data.sync_index);
                     retval = -EINVAL;
                     break;
                 }
                 
                 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
-                                &sc->pdos[data.direction], data.pdo_pos))) {
+                                &sc->sync_configs[data.sync_index].pdos,
+                                data.pdo_pos))) {
                     EC_ERR("Invalid Pdo position!\n");
                     retval = -EINVAL;
                     break;
@@ -929,14 +933,16 @@
                     break;
                 }
 
-                if (data.direction > EC_DIR_INPUT) {
-                    EC_ERR("Invalid direction %u!\n", data.direction);
+                if (data.sync_index >= EC_MAX_SYNCS) {
+                    EC_ERR("Invalid sync manager index %u!\n",
+                            data.sync_index);
                     retval = -EINVAL;
                     break;
                 }
                 
                 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
-                                &sc->pdos[data.direction], data.pdo_pos))) {
+                                &sc->sync_configs[data.sync_index].pdos,
+                                data.pdo_pos))) {
                     EC_ERR("Invalid Pdo position!\n");
                     retval = -EINVAL;
                     break;
--- a/master/domain.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/domain.c	Thu Jun 26 13:16:15 2008 +0000
@@ -201,7 +201,7 @@
     uint32_t datagram_offset;
     size_t datagram_size;
     unsigned int datagram_count;
-    unsigned int datagram_used[2];
+    unsigned int datagram_used[EC_DIR_COUNT];
     ec_fmmu_config_t *fmmu;
     const ec_datagram_t *datagram;
 
--- a/master/fmmu_config.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/fmmu_config.c	Thu Jun 26 13:16:15 2008 +0000
@@ -55,15 +55,18 @@
         ec_fmmu_config_t *fmmu, /**< EtherCAT FMMU configuration. */
         ec_slave_config_t *sc, /**< EtherCAT slave configuration. */
         ec_domain_t *domain, /**< EtherCAT domain. */
+        uint8_t sync_index, /**< Sync manager index to use. */
         ec_direction_t dir /**< Pdo direction. */
         )
 {
     INIT_LIST_HEAD(&fmmu->list);
     fmmu->sc = sc;
+    fmmu->sync_index = sync_index;
     fmmu->dir = dir;
 
     fmmu->logical_start_address = domain->data_size;
-    fmmu->data_size = ec_pdo_list_total_size(&sc->pdos[dir]);
+    fmmu->data_size = ec_pdo_list_total_size(
+            &sc->sync_configs[sync_index].pdos);
 
     ec_domain_add_fmmu_config(domain, fmmu);
 }
@@ -81,10 +84,10 @@
         )
 {
     if (fmmu->sc->master->debug_level) {
-        EC_DBG("FMMU: LogAddr 0x%08X, Size %3u, PhysAddr 0x%04X, Dir %s\n",
-               fmmu->logical_start_address, fmmu->data_size,
-               sync->physical_start_address,
-               (sync->control_register & 0x04) ? "out" : "in");
+        EC_DBG("FMMU: LogAddr 0x%08X, Size %3u, PhysAddr 0x%04X, SM%u, "
+                "Dir %s\n", fmmu->logical_start_address, fmmu->data_size,
+               sync->physical_start_address, fmmu->sync_index,
+               fmmu->dir == EC_DIR_INPUT ? "in" : "out");
     }
 
     EC_WRITE_U32(data,      fmmu->logical_start_address);
@@ -93,7 +96,7 @@
     EC_WRITE_U8 (data + 7,  0x07); // logical end bit
     EC_WRITE_U16(data + 8,  sync->physical_start_address);
     EC_WRITE_U8 (data + 10, 0x00); // physical start bit
-    EC_WRITE_U8 (data + 11, (sync->control_register & 0x04) ? 0x02 : 0x01);
+    EC_WRITE_U8 (data + 11, fmmu->dir == EC_DIR_INPUT ? 0x01 : 0x02);
     EC_WRITE_U16(data + 12, 0x0001); // enable
     EC_WRITE_U16(data + 14, 0x0000); // reserved
 }
--- a/master/fmmu_config.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/fmmu_config.h	Thu Jun 26 13:16:15 2008 +0000
@@ -53,8 +53,8 @@
     struct list_head list; /**< List node used by domain. */
     const ec_slave_config_t *sc; /**< EtherCAT slave config. */
     const ec_domain_t *domain; /**< Domain. */
-    ec_direction_t dir; /**< Pdo direction. */
-
+    uint8_t sync_index; /**< Index of sync manager to use. */
+    ec_direction_t dir; /**< FMMU direction. */
     uint32_t logical_start_address; /**< Logical start address. */
     unsigned int data_size; /**< Covered Pdo size. */
 } ec_fmmu_config_t;
@@ -62,7 +62,7 @@
 /*****************************************************************************/
 
 void ec_fmmu_config_init(ec_fmmu_config_t *, ec_slave_config_t *,
-        ec_domain_t *, ec_direction_t);
+        ec_domain_t *, uint8_t, ec_direction_t);
 
 void ec_fmmu_config_page(const ec_fmmu_config_t *, const ec_sync_t *,
         uint8_t *);
--- a/master/fsm_coe_map.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/fsm_coe_map.c	Thu Jun 26 13:16:15 2008 +0000
@@ -55,7 +55,7 @@
 void ec_fsm_coe_map_state_end(ec_fsm_coe_map_t *);
 void ec_fsm_coe_map_state_error(ec_fsm_coe_map_t *);
 
-void ec_fsm_coe_map_action_next_dir(ec_fsm_coe_map_t *);
+void ec_fsm_coe_map_action_next_sync(ec_fsm_coe_map_t *);
 void ec_fsm_coe_map_action_next_pdo(ec_fsm_coe_map_t *);
 void ec_fsm_coe_map_action_next_pdo_entry(ec_fsm_coe_map_t *);
 
@@ -134,50 +134,46 @@
  *  state functions
  *****************************************************************************/
 
-/**
- * Start reading Pdo assignment.
- */
-
+/** Start reading Pdo assignment.
+ */
 void ec_fsm_coe_map_state_start(
         ec_fsm_coe_map_t *fsm /**< finite state machine */
         )
 {
-    // read Pdo assignment for first direction
-    fsm->dir = (ec_direction_t) -1; // next is EC_DIR_OUTPUT
-    ec_fsm_coe_map_action_next_dir(fsm);
-}
-
-/*****************************************************************************/
-
-/**
- * Read Pdo assignment of next direction manager.
- */
-
-void ec_fsm_coe_map_action_next_dir(
-        ec_fsm_coe_map_t *fsm /**< finite state machine */
+    // read Pdo assignment for first sync manager
+    fsm->sync_index = 0xff; // next is 0
+    ec_fsm_coe_map_action_next_sync(fsm);
+}
+
+/*****************************************************************************/
+
+/** Read Pdo assignment of next sync manager.
+ */
+void ec_fsm_coe_map_action_next_sync(
+        ec_fsm_coe_map_t *fsm /**< Finite state machine */
         )
 {
     ec_slave_t *slave = fsm->slave;
 
-    fsm->dir++;
+    fsm->sync_index++;
 
     if (slave->master->debug_level)
-        EC_DBG("Processing dir %u of slave %u.\n",
-                fsm->dir, slave->ring_position);
-
-    for (; fsm->dir <= EC_DIR_INPUT; fsm->dir++) {
-
-        if (!(fsm->sync = ec_slave_get_pdo_sync(slave, fsm->dir))) {
+        EC_DBG("Processing SM%u of slave %u.\n",
+                fsm->sync_index, slave->ring_position);
+
+    for (; fsm->sync_index < EC_MAX_SYNCS; fsm->sync_index++) {
+        if (!(fsm->sync = ec_slave_get_sync(slave, fsm->sync_index))) {
             if (slave->master->debug_level)
-                EC_DBG("No sync manager for direction %u!\n", fsm->dir);
+                EC_DBG("Slave %u does not provide a configuration for "
+                        "SM%u!\n", fsm->slave->ring_position, fsm->sync_index);
             continue;
         }
 
-        fsm->sync_sdo_index = 0x1C10 + fsm->sync->index;
+        fsm->sync_sdo_index = 0x1C10 + fsm->sync_index;
 
         if (slave->master->debug_level)
-            EC_DBG("Reading Pdo assignment of sync manager %u of slave %u.\n",
-                    fsm->sync->index, slave->ring_position);
+            EC_DBG("Reading Pdo assignment of SM%u of slave %u.\n",
+                    fsm->sync_index, slave->ring_position);
 
         ec_pdo_list_clear_pdos(&fsm->pdos);
 
@@ -226,7 +222,7 @@
     fsm->sync_subindices = EC_READ_U8(fsm->request.data);
 
     if (fsm->slave->master->debug_level)
-        EC_DBG("  %u Pdos assigned.\n", fsm->sync_subindices);
+        EC_DBG("%u Pdos assigned.\n", fsm->sync_subindices);
 
     // read first Pdo
     fsm->sync_subindex = 1;
@@ -263,8 +259,8 @@
     fsm->sync->assign_source = EC_ASSIGN_COE;
     ec_pdo_list_clear_pdos(&fsm->pdos);
 
-    // next direction
-    ec_fsm_coe_map_action_next_dir(fsm);
+    // next sync manager
+    ec_fsm_coe_map_action_next_sync(fsm);
 }
 
 /*****************************************************************************/
@@ -304,10 +300,10 @@
 
     ec_pdo_init(fsm->pdo);
     fsm->pdo->index = EC_READ_U16(fsm->request.data);
-    fsm->pdo->dir = ec_sync_direction(fsm->sync);
+    fsm->pdo->sync_index = fsm->sync_index;
 
     if (fsm->slave->master->debug_level)
-        EC_DBG("  Pdo 0x%04X.\n", fsm->pdo->index);
+        EC_DBG("Pdo 0x%04X.\n", fsm->pdo->index);
 
     list_add_tail(&fsm->pdo->list, &fsm->pdos.list);
 
@@ -348,7 +344,7 @@
     fsm->pdo_subindices = EC_READ_U8(fsm->request.data);
 
     if (fsm->slave->master->debug_level)
-        EC_DBG("    %u Pdo entries mapped.\n", fsm->pdo_subindices);
+        EC_DBG("%u Pdo entries mapped.\n", fsm->pdo_subindices);
 
     // read first Pdo entry
     fsm->pdo_subindex = 1;
@@ -432,7 +428,7 @@
         }
 
         if (fsm->slave->master->debug_level) {
-            EC_DBG("    Pdo entry 0x%04X:%02X, %u bit,  \"%s\".\n",
+            EC_DBG("Pdo entry 0x%04X:%02X, %u bit, \"%s\".\n",
                     pdo_entry->index, pdo_entry->subindex,
                     pdo_entry->bit_length,
                     pdo_entry->name ? pdo_entry->name : "???");
--- a/master/fsm_coe_map.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/fsm_coe_map.h	Thu Jun 26 13:16:15 2008 +0000
@@ -61,7 +61,7 @@
     ec_slave_t *slave; /**< EtherCAT slave */
     ec_sdo_request_t request; /**< Sdo request */
 
-    ec_direction_t dir; /**< index of the current sync manager */
+    uint8_t sync_index; /**< Index of the current sync manager. */
     ec_sync_t *sync; /**< Pdo sync manager. */
     uint16_t sync_sdo_index; /**< Index of the mapping Sdo. */
     uint8_t sync_subindices; /**< number of mapped Pdos */
--- a/master/fsm_pdo_assign.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/fsm_pdo_assign.c	Thu Jun 26 13:16:15 2008 +0000
@@ -53,7 +53,7 @@
 void ec_fsm_pdo_assign_state_end(ec_fsm_pdo_assign_t *);
 void ec_fsm_pdo_assign_state_error(ec_fsm_pdo_assign_t *);
 
-void ec_fsm_pdo_assign_next_dir(ec_fsm_pdo_assign_t *);
+void ec_fsm_pdo_assign_next_sync(ec_fsm_pdo_assign_t *);
 
 /*****************************************************************************/
 
@@ -151,46 +151,50 @@
         return;
     }
 
-    fsm->dir = (ec_direction_t) -1; // next is EC_DIR_OUTPUT
-    fsm->num_configured_dirs = 0;
-    ec_fsm_pdo_assign_next_dir(fsm);
-}
-
-/*****************************************************************************/
-
-/** Process Pdo assignment of next direction.
- */
-void ec_fsm_pdo_assign_next_dir(
-        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
-        )
-{
-    fsm->dir++;
-
-    for (; fsm->dir <= EC_DIR_INPUT; fsm->dir++) {
-        fsm->pdos = &fsm->slave->config->pdos[fsm->dir];
+    fsm->sync_index = 0xff; // next is zero
+    fsm->num_configured_syncs = 0;
+    ec_fsm_pdo_assign_next_sync(fsm);
+}
+
+/*****************************************************************************/
+
+/** Process Pdo assignment of next sync manager.
+ */
+void ec_fsm_pdo_assign_next_sync(
+        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+    fsm->sync_index++;
+
+    for (; fsm->sync_index < EC_MAX_SYNCS; fsm->sync_index++) {
+        fsm->pdos = &fsm->slave->config->sync_configs[fsm->sync_index].pdos;
         
-        if (!(fsm->sync = ec_slave_get_pdo_sync(fsm->slave, fsm->dir))) {
+        if (!(fsm->sync = ec_slave_get_sync(fsm->slave, fsm->sync_index))) {
             if (!list_empty(&fsm->pdos->list)) {
-                EC_ERR("No sync manager for direction %u!\n", fsm->dir);
+                EC_ERR("Slave %u does not provide a configuration for sync "
+                        "manager %u!\n", fsm->slave->ring_position,
+                        fsm->sync_index);
                 fsm->state = ec_fsm_pdo_assign_state_end;
                 return;
             }
             continue;
         }
 
-        if (fsm->slave->master->debug_level) {
-            EC_DBG("Sync Pdos: ");
-            ec_pdo_list_print(&fsm->sync->pdos);
-            printk("\n");
-            EC_DBG("Config Pdos: ");
-            ec_pdo_list_print(fsm->pdos);
-            printk("\n");
-        }
-
         // check if assignment has to be altered
         if (ec_pdo_list_equal(&fsm->sync->pdos, fsm->pdos))
             continue;
 
+        if (fsm->slave->master->debug_level) {
+            EC_DBG("Pdo assignment of SM%u differs in slave %u:\n",
+                    fsm->sync_index, fsm->slave->ring_position);
+            EC_DBG("Currently assigned Pdos: ");
+            ec_pdo_list_print(&fsm->sync->pdos);
+            printk("\n");
+            EC_DBG("Pdos to assign: ");
+            ec_pdo_list_print(fsm->pdos);
+            printk("\n");
+        }
+
         // Pdo assignment has to be changed. Does the slave support this?
         if (!(fsm->slave->sii.mailbox_protocols & EC_MBOX_COE)
                 || (fsm->slave->sii.has_general
@@ -201,11 +205,11 @@
             return;
         }
 
-        fsm->num_configured_dirs++;
+        fsm->num_configured_syncs++;
 
         if (fsm->slave->master->debug_level) {
             EC_DBG("Changing Pdo assignment for SM%u of slave %u.\n",
-                    fsm->sync->index, fsm->slave->ring_position);
+                    fsm->sync_index, fsm->slave->ring_position);
         }
 
         if (ec_sdo_request_alloc(&fsm->request, 2)) {
@@ -216,10 +220,10 @@
         // set mapped Pdo count to zero
         EC_WRITE_U8(fsm->request.data, 0); // zero Pdos mapped
         fsm->request.data_size = 1;
-        ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync->index, 0);
+        ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, 0);
         ecrt_sdo_request_write(&fsm->request);
         if (fsm->slave->master->debug_level)
-            EC_DBG("Setting Pdo count to zero for SM%u.\n", fsm->sync->index);
+            EC_DBG("Setting Pdo count to zero for SM%u.\n", fsm->sync_index);
 
         fsm->state = ec_fsm_pdo_assign_state_zero_count;
         ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
@@ -227,7 +231,7 @@
         return;
     }
 
-    if (fsm->slave->master->debug_level && !fsm->num_configured_dirs)
+    if (fsm->slave->master->debug_level && !fsm->num_configured_syncs)
         EC_DBG("Pdo assignments of slave %u are already configured"
                 " correctly.\n", fsm->slave->ring_position);
     fsm->state = ec_fsm_pdo_assign_state_end;
@@ -259,7 +263,7 @@
     EC_WRITE_U16(fsm->request.data, fsm->pdo->index);
     fsm->request.data_size = 2;
     ec_sdo_request_address(&fsm->request,
-            0x1C10 + fsm->sync->index, fsm->pdo_count);
+            0x1C10 + fsm->sync_index, fsm->pdo_count);
     ecrt_sdo_request_write(&fsm->request);
     if (fsm->slave->master->debug_level)
         EC_DBG("Assigning Pdo 0x%04X at position %u.\n",
@@ -293,8 +297,8 @@
     if (!(fsm->pdo = ec_fsm_pdo_assign_next_pdo(fsm, &fsm->pdos->list))) {
         if (fsm->slave->master->debug_level)
             EC_DBG("No Pdos to assign for SM%u of slave %u.\n",
-                    fsm->sync->index, fsm->slave->ring_position);
-        ec_fsm_pdo_assign_next_dir(fsm);
+                    fsm->sync_index, fsm->slave->ring_position);
+        ec_fsm_pdo_assign_next_sync(fsm);
         return;
     }
 
@@ -315,7 +319,7 @@
 
     if (!ec_fsm_coe_success(fsm->fsm_coe)) {
         EC_ERR("Failed to map Pdo 0x%04X for SM%u of slave %u.\n",
-                fsm->pdo->index, fsm->sync->index, fsm->slave->ring_position);
+                fsm->pdo->index, fsm->sync_index, fsm->slave->ring_position);
         fsm->state = ec_fsm_pdo_assign_state_error;
         return;
     }
@@ -325,7 +329,7 @@
         // no more Pdos to map. write Pdo count
         EC_WRITE_U8(fsm->request.data, fsm->pdo_count);
         fsm->request.data_size = 1;
-        ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync->index, 0);
+        ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, 0);
         ecrt_sdo_request_write(&fsm->request);
         if (fsm->slave->master->debug_level)
             EC_DBG("Setting number of assigned Pdos to %u.\n",
@@ -361,10 +365,10 @@
 
     if (fsm->slave->master->debug_level)
         EC_DBG("Successfully configured Pdo assignment for SM%u of"
-                " slave %u.\n", fsm->sync->index, fsm->slave->ring_position);
-
-    // assignment for this direction finished
-    ec_fsm_pdo_assign_next_dir(fsm);
+                " slave %u.\n", fsm->sync_index, fsm->slave->ring_position);
+
+    // assignment for this sync manager finished
+    ec_fsm_pdo_assign_next_sync(fsm);
 }
 
 /******************************************************************************
--- a/master/fsm_pdo_assign.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/fsm_pdo_assign.h	Thu Jun 26 13:16:15 2008 +0000
@@ -62,10 +62,11 @@
     ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use. */
     ec_slave_t *slave; /**< Slave the FSM runs on. */
 
-    ec_direction_t dir; /**< Current direction. */
+    uint8_t sync_index; /**< Current sync manager index. */
     const ec_pdo_list_t *pdos; /**< Target Pdo assignment. */
     const ec_sync_t *sync; /**< Current sync manager. */
-    unsigned int num_configured_dirs; /**< Number of configured directions. */
+    unsigned int num_configured_syncs; /**< Number of configured
+                                         assignments. */
     const ec_pdo_t *pdo; /**< Current Pdo. */
 
     ec_sdo_request_t request; /**< Sdo request. */
--- a/master/fsm_pdo_mapping.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/fsm_pdo_mapping.c	Thu Jun 26 13:16:15 2008 +0000
@@ -161,12 +161,12 @@
         ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
         )
 {
-    ec_direction_t dir;
+    uint8_t sync_index;
     const ec_pdo_list_t *pdos;
     const ec_pdo_t *pdo, *assigned_pdo;
     
-    for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) {
-        pdos = &fsm->slave->config->pdos[dir];
+    for (sync_index = 0; sync_index < EC_MAX_SYNCS; sync_index++) {
+        pdos = &fsm->slave->config->sync_configs[sync_index].pdos;
 
         list_for_each_entry(pdo, &pdos->list, list) {
             if (fsm->pdo) { // there was a Pdo mapping changed in the last run
@@ -251,15 +251,17 @@
 {
     uint32_t value;
 
+    if (fsm->slave->master->debug_level)
+        EC_DBG("Mapping Pdo entry 0x%04X:%02X (%u bit) at position %u.\n",
+                fsm->entry->index, fsm->entry->subindex,
+                fsm->entry->bit_length, fsm->entry_count);
+
     value = fsm->entry->index << 16
         | fsm->entry->subindex << 8 | fsm->entry->bit_length;
     EC_WRITE_U32(fsm->request.data, value);
     fsm->request.data_size = 4;
     ec_sdo_request_address(&fsm->request, fsm->pdo->index, fsm->entry_count);
     ecrt_sdo_request_write(&fsm->request);
-    if (fsm->slave->master->debug_level)
-        EC_DBG("Configuring Pdo entry %08X at position %u.\n",
-                value, fsm->entry_count);
     
     fsm->state = ec_fsm_pdo_mapping_state_add_entry;
     ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
--- a/master/fsm_slave_config.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/fsm_slave_config.c	Thu Jun 26 13:16:15 2008 +0000
@@ -301,7 +301,9 @@
                 EC_SYNC_PAGE_SIZE * slave->sii.sync_count);
 
         for (i = 0; i < 2; i++) {
-            ec_sync_config(&slave->sii.syncs[i], slave->sii.syncs[i].length,
+            ec_sync_page(&slave->sii.syncs[i], i,
+                    slave->sii.syncs[i].default_length,
+                    EC_DIR_INVALID, // use default direction
                     datagram->data + EC_SYNC_PAGE_SIZE * i);
         }
     } else { // no mailbox sync manager configurations provided
@@ -316,19 +318,21 @@
                 EC_SYNC_PAGE_SIZE * 2);
         memset(datagram->data, 0x00, EC_SYNC_PAGE_SIZE * 2);
 
-        ec_sync_init(&sync, slave, 0);
+        ec_sync_init(&sync, slave);
         sync.physical_start_address = slave->sii.rx_mailbox_offset;
         sync.control_register = 0x26;
         sync.enable = 1;
-        ec_sync_config(&sync, slave->sii.rx_mailbox_size,
-                datagram->data + EC_SYNC_PAGE_SIZE * sync.index);
-
-        ec_sync_init(&sync, slave, 1);
+        ec_sync_page(&sync, 0, slave->sii.rx_mailbox_size,
+                EC_DIR_INVALID, // use default direction
+                datagram->data);
+
+        ec_sync_init(&sync, slave);
         sync.physical_start_address = slave->sii.tx_mailbox_offset;
         sync.control_register = 0x22;
         sync.enable = 1;
-        ec_sync_config(&sync, slave->sii.tx_mailbox_size,
-                datagram->data + EC_SYNC_PAGE_SIZE * sync.index);
+        ec_sync_page(&sync, 1, slave->sii.tx_mailbox_size,
+                EC_DIR_INVALID, // use default direction
+                datagram->data + EC_SYNC_PAGE_SIZE);
     }
 
     fsm->retries = EC_FSM_RETRIES;
@@ -499,8 +503,9 @@
     ec_slave_t *slave = fsm->slave;
     ec_datagram_t *datagram = fsm->datagram;
     unsigned int i, offset, num_pdo_syncs;
+    uint8_t sync_index;
     const ec_sync_t *sync;
-    ec_direction_t dir;
+    const ec_sync_config_t *sync_config;
     uint16_t size;
 
     if (slave->sii.mailbox_protocols) {
@@ -524,10 +529,12 @@
     memset(datagram->data, 0x00, EC_SYNC_PAGE_SIZE * num_pdo_syncs);
 
     for (i = 0; i < num_pdo_syncs; i++) {
-        sync = &slave->sii.syncs[i + offset];
-        dir = ec_sync_direction(sync);
-        size = ec_pdo_list_total_size(&slave->config->pdos[dir]);
-        ec_sync_config(sync, size, datagram->data + EC_SYNC_PAGE_SIZE * i);
+        sync_index = i + offset;
+        sync = &slave->sii.syncs[sync_index];
+        sync_config = &slave->config->sync_configs[sync_index];
+        size = ec_pdo_list_total_size(&sync_config->pdos);
+        ec_sync_page(sync, sync_index, size, sync_config->dir,
+                datagram->data + EC_SYNC_PAGE_SIZE * i);
     }
 
     fsm->retries = EC_FSM_RETRIES;
@@ -654,7 +661,7 @@
     memset(datagram->data, 0x00, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
     for (i = 0; i < slave->config->used_fmmus; i++) {
         fmmu = &slave->config->fmmu_configs[i];
-        if (!(sync = ec_slave_get_pdo_sync(slave, fmmu->dir))) {
+        if (!(sync = ec_slave_get_sync(slave, fmmu->sync_index))) {
             slave->error_flag = 1;
             fsm->state = ec_fsm_slave_config_state_error;
             EC_ERR("Failed to determine Pdo sync manager for FMMU on slave"
--- a/master/fsm_slave_scan.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/fsm_slave_scan.c	Thu Jun 26 13:16:15 2008 +0000
@@ -338,7 +338,7 @@
     }
 
     dl_status = EC_READ_U16(datagram->data);
-    for (i = 0; i < EC_SLAVE_MAX_PORTS; i++) {
+    for (i = 0; i < EC_MAX_PORTS; i++) {
         slave->ports[i].dl_link = dl_status & (1 << (4 + i)) ? 1 : 0;
         slave->ports[i].dl_loop = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
         slave->ports[i].dl_signal = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
--- a/master/globals.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/globals.h	Thu Jun 26 13:16:15 2008 +0000
@@ -90,6 +90,12 @@
 /** Word offset of first SII category. */
 #define EC_FIRST_SII_CATEGORY_OFFSET 0x40
 
+/** Maximum number of slave ports. */
+#define EC_MAX_PORTS 4
+
+/** Maximum number of sync managers per slave. */
+#define EC_MAX_SYNCS 16
+
 /** Size of a sync manager configuration page. */
 #define EC_SYNC_PAGE_SIZE 8
 
@@ -99,9 +105,6 @@
 /** Size of an FMMU configuration page. */
 #define EC_FMMU_PAGE_SIZE 16
 
-/** Maximum number of slave ports. */
-#define EC_SLAVE_MAX_PORTS 4
-
 /** Slave state mask.
  *
  * Apply this mask to a slave state byte to get the slave state without
--- a/master/ioctl.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/ioctl.h	Thu Jun 26 13:16:15 2008 +0000
@@ -146,7 +146,6 @@
     uint32_t pdo_pos;
 
     // outputs
-    uint8_t dir;
     uint16_t index;
     uint8_t entry_count;
     int8_t name[EC_IOCTL_STRING_SIZE];
@@ -192,7 +191,8 @@
     // outputs
     uint16_t slave_config_alias;
     uint16_t slave_config_position;
-    uint8_t fmmu_dir;
+    uint8_t sync_index;
+    ec_direction_t dir;
 	uint32_t logical_address;
     uint32_t data_size;
 } ec_ioctl_domain_fmmu_t;
@@ -291,7 +291,10 @@
     uint16_t position;
     uint32_t vendor_id;
     uint32_t product_code;
-    uint32_t pdo_count[2];
+    struct {
+        ec_direction_t dir;
+        uint32_t pdo_count;
+    } syncs[16];
     uint32_t sdo_count;
     uint8_t attached;
 } ec_ioctl_config_t;
@@ -301,8 +304,8 @@
 typedef struct {
     // inputs
     uint32_t config_index;
-    uint32_t direction;
-    uint32_t pdo_pos;
+    uint8_t sync_index;
+    uint16_t pdo_pos;
 
     // outputs
     uint16_t index;
@@ -315,9 +318,9 @@
 typedef struct {
     // inputs
     uint32_t config_index;
-    uint32_t direction;
-    uint32_t pdo_pos;
-    uint32_t entry_pos;
+    uint8_t sync_index;
+    uint16_t pdo_pos;
+    uint8_t entry_pos;
 
     // outputs
     uint16_t index;
--- a/master/master.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/master.c	Thu Jun 26 13:16:15 2008 +0000
@@ -1306,10 +1306,6 @@
     }
 
     if (found) { // config with same alias/position already existing
-        if (master->debug_level) {
-            EC_INFO("Using existing slave configuration for %u:%u\n",
-                    alias, position);
-        }
         if (sc->vendor_id != vendor_id || sc->product_code != product_code) {
             EC_ERR("Slave type mismatch. Slave was configured as"
                     " 0x%08X/0x%08X before. Now configuring with"
@@ -1318,11 +1314,9 @@
             return NULL;
         }
     } else {
-        if (master->debug_level) {
-            EC_INFO("Creating slave configuration for %u:%u,"
-                    " 0x%08X/0x%08X.\n", alias, position, vendor_id,
-                    product_code);
-        }
+        if (master->debug_level)
+            EC_DBG("Creating slave configuration for %u:%u, 0x%08X/0x%08X.\n",
+                    alias, position, vendor_id, product_code);
 
         if (!(sc = (ec_slave_config_t *) kmalloc(sizeof(ec_slave_config_t),
                         GFP_KERNEL))) {
@@ -1334,8 +1328,8 @@
                 alias, position, vendor_id, product_code);
 
         // try to find the addressed slave
-        if (!ec_slave_config_attach(sc))
-            ec_slave_config_load_default_assignment(sc);
+        ec_slave_config_attach(sc);
+        ec_slave_config_load_default_sync_config(sc);
 
         list_add_tail(&sc->list, &master->configs);
     }
--- a/master/pdo.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/pdo.c	Thu Jun 26 13:16:15 2008 +0000
@@ -61,7 +61,6 @@
  */
 int ec_pdo_init_copy(ec_pdo_t *pdo, const ec_pdo_t *other_pdo)
 {
-    pdo->dir = other_pdo->dir;
     pdo->index = other_pdo->index;
     pdo->sync_index = other_pdo->sync_index;
     pdo->name = NULL;
--- a/master/pdo.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/pdo.h	Thu Jun 26 13:16:15 2008 +0000
@@ -54,9 +54,8 @@
  */
 typedef struct {
     struct list_head list; /**< List item. */
-    ec_direction_t dir; /**< Pdo direction. */
     uint16_t index; /**< Pdo index. */
-    int8_t sync_index; /**< Assigned sync manager. */
+    int8_t sync_index; /**< Assigned sync manager. \todo remove? */
     char *name; /**< Pdo name. */
     struct list_head entries; /**< List of Pdo entries. */
 } ec_pdo_t;
--- a/master/pdo_list.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/pdo_list.c	Thu Jun 26 13:16:15 2008 +0000
@@ -121,7 +121,6 @@
  */
 ec_pdo_t *ec_pdo_list_add_pdo(
         ec_pdo_list_t *pl, /**< Pdo list. */
-        ec_direction_t dir, /**< Direction. */
         uint16_t index /**< Pdo index. */
         )
 {
@@ -133,7 +132,6 @@
     }
 
     ec_pdo_init(pdo);
-    pdo->dir = dir;
     pdo->index = index;
     list_add_tail(&pdo->list, &pl->list);
     return pdo;
--- a/master/pdo_list.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/pdo_list.h	Thu Jun 26 13:16:15 2008 +0000
@@ -63,8 +63,7 @@
 
 void ec_pdo_list_clear_pdos(ec_pdo_list_t *);
 
-ec_pdo_t *ec_pdo_list_add_pdo(ec_pdo_list_t *, ec_direction_t,
-        uint16_t);
+ec_pdo_t *ec_pdo_list_add_pdo(ec_pdo_list_t *, uint16_t);
 int ec_pdo_list_add_pdo_copy(ec_pdo_list_t *, const ec_pdo_t *);
 
 int ec_pdo_list_copy(ec_pdo_list_t *, const ec_pdo_list_t *);
--- a/master/sdo_request.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/sdo_request.c	Thu Jun 26 13:16:15 2008 +0000
@@ -75,7 +75,7 @@
     req->data = NULL;
     req->mem_size = 0;
     req->data_size = 0;
-    req->dir = EC_DIR_OUTPUT;
+    req->dir = EC_DIR_INVALID;
     req->issue_timeout = 0; // no timeout
     req->response_timeout = EC_SDO_REQUEST_RESPONSE_TIMEOUT;
     req->state = EC_REQUEST_INIT;
--- a/master/slave.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/slave.c	Thu Jun 26 13:16:15 2008 +0000
@@ -87,7 +87,7 @@
     slave->base_build = 0;
     slave->base_fmmu_count = 0;
 
-    for (i = 0; i < EC_SLAVE_MAX_PORTS; i++) {
+    for (i = 0; i < EC_MAX_PORTS; i++) {
         slave->ports[i].dl_link = 0;
         slave->ports[i].dl_loop = 0;
         slave->ports[i].dl_signal = 0;
@@ -365,6 +365,10 @@
 
     if (count) {
         total_count = count + slave->sii.sync_count;
+        if (total_count > EC_MAX_SYNCS) {
+            EC_ERR("Exceeded maximum number of sync managers!\n");
+            return -1;
+        }
         memsize = sizeof(ec_sync_t) * total_count;
         if (!(syncs = kmalloc(memsize, GFP_KERNEL))) {
             EC_ERR("Failed to allocate %u bytes for sync managers.\n",
@@ -380,9 +384,9 @@
             index = i + slave->sii.sync_count;
             sync = &syncs[index];
 
-            ec_sync_init(sync, slave, index);
+            ec_sync_init(sync, slave);
             sync->physical_start_address = EC_READ_U16(data);
-            sync->length = EC_READ_U16(data + 2);
+            sync->default_length = EC_READ_U16(data + 2);
             sync->control_register = EC_READ_U8(data + 4);
             sync->enable = EC_READ_U8(data + 6);
         }
@@ -421,7 +425,6 @@
         }
 
         ec_pdo_init(pdo);
-        pdo->dir = dir;
         pdo->index = EC_READ_U16(data);
         entry_count = EC_READ_U8(data + 2);
         pdo->sync_index = EC_READ_U8(data + 3);
@@ -462,12 +465,11 @@
         if (pdo->sync_index >= 0) {
             ec_sync_t *sync;
 
-            if (pdo->sync_index >= slave->sii.sync_count) {
+            if (!(sync = ec_slave_get_sync(slave, pdo->sync_index))) {
                 EC_ERR("Invalid SM index %i for Pdo 0x%04X in slave %u.",
                         pdo->sync_index, pdo->index, slave->ring_position);
                 return -1;
             }
-            sync = &slave->sii.syncs[pdo->sync_index];
 
             if (ec_pdo_list_add_pdo_copy(&sync->pdos, pdo))
                 return -1;
@@ -564,37 +566,20 @@
 
 /*****************************************************************************/
 
-/** Get the sync manager for either Rx- or Tx-Pdos.
- *
- * \todo This seems not to be correct in every case...
+/** Get the sync manager given an index.
+ *
  * \return pointer to sync manager, or NULL.
  */
-ec_sync_t *ec_slave_get_pdo_sync(
+ec_sync_t *ec_slave_get_sync(
         ec_slave_t *slave, /**< EtherCAT slave. */
-        ec_direction_t dir /**< Input or output. */
-        )
-{
-    unsigned int sync_index;
-
-    if (dir != EC_DIR_INPUT && dir != EC_DIR_OUTPUT) {
-        EC_ERR("Invalid direction!\n");
+        uint8_t sync_index /**< Sync manager index. */
+        )
+{
+    if (sync_index < slave->sii.sync_count) {
+        return &slave->sii.syncs[sync_index];
+    } else {
         return NULL;
     }
-
-    if (slave->sii.sync_count != 1) {
-        sync_index = (unsigned int) dir;
-        if (slave->sii.mailbox_protocols) sync_index += 2;
-
-        if (sync_index >= slave->sii.sync_count)
-            return NULL;
-    } else { // sync_count == 1
-        // A single sync manager may be used for inputs OR outputs!
-        if (ec_sync_direction(&slave->sii.syncs[0]) != dir)
-            return NULL;
-        sync_index = 0;
-    }
-
-    return &slave->sii.syncs[sync_index];
 }
 
 /*****************************************************************************/
--- a/master/slave.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/slave.h	Thu Jun 26 13:16:15 2008 +0000
@@ -79,7 +79,7 @@
     char *image; /**< Image name. */
     char *order; /**< Order number. */
     char *name; /**< Slave name. */
-    uint8_t physical_layer[EC_SLAVE_MAX_PORTS]; /**< Port media. */
+    uint8_t physical_layer[EC_MAX_PORTS]; /**< Port media. */
     ec_sii_coe_details_t coe_details; /**< CoE detail flags. */
     ec_sii_general_flags_t general_flags; /**< General flags. */
     int16_t current_on_ebus; /**< Power consumption in mA. */
@@ -128,7 +128,7 @@
     uint16_t base_fmmu_count; /**< Number of supported FMMUs. */
 
     // data link status
-    ec_slave_port_t ports[EC_SLAVE_MAX_PORTS];
+    ec_slave_port_t ports[EC_MAX_PORTS];
 
     // SII
     uint16_t *sii_words; /**< Complete SII image. */
@@ -161,7 +161,8 @@
         ec_direction_t);
 
 // misc.
-ec_sync_t *ec_slave_get_pdo_sync(ec_slave_t *, ec_direction_t); 
+ec_sync_t *ec_slave_get_sync(ec_slave_t *, uint8_t); 
+
 void ec_slave_sdo_dict_info(const ec_slave_t *,
         unsigned int *, unsigned int *);
 ec_sdo_t *ec_slave_get_sdo(ec_slave_t *, uint16_t);
--- a/master/slave_config.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/slave_config.c	Thu Jun 26 13:16:15 2008 +0000
@@ -61,7 +61,7 @@
         uint32_t product_code /**< Expected product code. */
         )
 {
-    ec_direction_t dir;
+    unsigned int i;
 
     sc->master = master;
     sc->alias = alias;
@@ -70,8 +70,8 @@
     sc->product_code = product_code;
     sc->slave = NULL;
 
-    for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
-        ec_pdo_list_init(&sc->pdos[dir]);
+    for (i = 0; i < EC_MAX_SYNCS; i++)
+        ec_sync_config_init(&sc->sync_configs[i]);
 
     INIT_LIST_HEAD(&sc->sdo_configs);
     INIT_LIST_HEAD(&sc->sdo_requests);
@@ -89,14 +89,14 @@
         ec_slave_config_t *sc /**< Slave configuration. */
         )
 {
-    ec_direction_t dir;
+    unsigned int i;
     ec_sdo_request_t *req, *next_req;
 
     ec_slave_config_detach(sc);
 
-    // Free Pdo mappings
-    for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
-        ec_pdo_list_clear(&sc->pdos[dir]);
+    // Free sync managers
+    for (i = 0; i < EC_MAX_SYNCS; i++)
+        ec_sync_config_clear(&sc->sync_configs[i]);
 
     // free all Sdo configurations
     list_for_each_entry_safe(req, next_req, &sc->sdo_configs, list) {
@@ -130,6 +130,7 @@
 int ec_slave_config_prepare_fmmu(
         ec_slave_config_t *sc, /**< Slave configuration. */
         ec_domain_t *domain, /**< Domain. */
+        uint8_t sync_index, /**< Sync manager index. */
         ec_direction_t dir /**< Pdo direction. */
         )
 {
@@ -139,7 +140,7 @@
     // FMMU configuration already prepared?
     for (i = 0; i < sc->used_fmmus; i++) {
         fmmu = &sc->fmmu_configs[i];
-        if (fmmu->domain == domain && fmmu->dir == dir)
+        if (fmmu->domain == domain && fmmu->sync_index == sync_index)
             return fmmu->logical_start_address;
     }
 
@@ -150,7 +151,7 @@
     }
 
     fmmu = &sc->fmmu_configs[sc->used_fmmus++];
-    ec_fmmu_config_init(fmmu, sc, domain, dir);
+    ec_fmmu_config_init(fmmu, sc, domain, sync_index, dir);
     return fmmu->logical_start_address;
 }
 
@@ -228,19 +229,25 @@
 
 /** Loads the default Pdo assignment from the slave object.
  */
-void ec_slave_config_load_default_assignment(ec_slave_config_t *sc)
-{
-    ec_direction_t dir;
-    ec_pdo_list_t *pdos;
-    ec_sync_t *sync;
+void ec_slave_config_load_default_sync_config(ec_slave_config_t *sc)
+{
+    uint8_t sync_index;
+    ec_sync_config_t *sync_config;
+    const ec_sync_t *sync;
 
     if (!sc->slave)
         return;
     
-    for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) {
-        pdos = &sc->pdos[dir];
-        if ((sync = ec_slave_get_pdo_sync(sc->slave, dir)))
-            ec_pdo_list_copy(pdos, &sync->pdos);
+    
+    for (sync_index = 0; sync_index < EC_MAX_SYNCS; sync_index++) {
+        sync_config = &sc->sync_configs[sync_index];
+        if ((sync = ec_slave_get_sync(sc->slave, sync_index))) {
+            sync_config->dir = ec_sync_default_direction(sync);
+            if (sync_config->dir == EC_DIR_INVALID)
+                EC_WARN("SM%u of slave %u has an invalid direction field!\n",
+                        sync_index, sc->slave->ring_position);
+            ec_pdo_list_copy(&sync_config->pdos, &sync->pdos);
+        }
     }
 }
 
@@ -253,50 +260,51 @@
         ec_pdo_t *pdo
         )
 {
+    unsigned int i;
     const ec_sync_t *sync;
     const ec_pdo_t *default_pdo;
 
-    if (sc->master->debug_level)
-        EC_DBG("Loading default configuration for Pdo 0x%04X in"
-                " config %u:%u.\n", pdo->index, sc->alias, sc->position);
-
-    if (!sc->slave) {
-        if (sc->master->debug_level)
-            EC_DBG("Failed to load default Pdo configuration for %u:%u:"
-                    " Slave not found.\n", sc->alias, sc->position);
+    if (!sc->slave)
         return;
-    }
-
-    if (!(sync = ec_slave_get_pdo_sync(sc->slave, pdo->dir))) {
-        if (sc->master->debug_level)
-            EC_DBG("Slave %u does not provide a default Pdo"
-                    " configuration!\n", sc->slave->ring_position);
-        return;
-    }
-
-    list_for_each_entry(default_pdo, &sync->pdos.list, list) {
-        if (default_pdo->index != pdo->index)
-            continue;
-
-        if (sc->master->debug_level)
-            EC_DBG("  Found Pdo name \"%s\".\n",
-                    default_pdo->name);
-
-        // try to take Pdo name from mapped one
-        ec_pdo_set_name(pdo, default_pdo->name);
-
-        // copy entries (= default Pdo configuration)
-        if (ec_pdo_copy_entries(pdo, default_pdo))
+
+    if (sc->master->debug_level)
+        EC_DBG("Loading default mapping for Pdo 0x%04X in config %u:%u.\n",
+                pdo->index, sc->alias, sc->position);
+
+    // find Pdo in any sync manager (it could be reassigned later)
+    for (i = 0; i < sc->slave->sii.sync_count; i++) {
+        sync = &sc->slave->sii.syncs[i];
+
+        list_for_each_entry(default_pdo, &sync->pdos.list, list) {
+            if (default_pdo->index != pdo->index)
+                continue;
+
+            if (default_pdo->name) {
+                if (sc->master->debug_level)
+                    EC_DBG("Found Pdo name \"%s\".\n", default_pdo->name);
+
+                // take Pdo name from assigned one
+                ec_pdo_set_name(pdo, default_pdo->name);
+            }
+
+            // copy entries (= default Pdo mapping)
+            if (ec_pdo_copy_entries(pdo, default_pdo))
+                return;
+
+            if (sc->master->debug_level) {
+                const ec_pdo_entry_t *entry;
+                list_for_each_entry(entry, &pdo->entries, list) {
+                    EC_DBG("Entry 0x%04X:%02X.\n",
+                            entry->index, entry->subindex);
+                }
+            }
+
             return;
-
-        if (sc->master->debug_level) {
-            const ec_pdo_entry_t *entry;
-            list_for_each_entry(entry, &pdo->entries, list) {
-                EC_DBG("    Entry 0x%04X:%02X.\n",
-                        entry->index, entry->subindex);
-            }
         }
     }
+
+    if (sc->master->debug_level)
+        EC_DBG("No default mapping found.\n");
 }
 
 /*****************************************************************************/
@@ -341,18 +349,49 @@
  *  Realtime interface
  *****************************************************************************/
 
+int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index,
+        ec_direction_t dir)
+{
+    ec_sync_config_t *sync_config;
+    
+    if (sc->master->debug_level)
+        EC_DBG("ecrt_slave_config_sync_manager(sc = 0x%x, sync_index = %u, "
+                "dir = %u)\n", (u32) sc, sync_index, dir);
+
+    if (sync_index >= EC_MAX_SYNCS) {
+        EC_ERR("Invalid sync manager index %u!\n", sync_index);
+        return -1;
+    }
+
+    if (dir != EC_DIR_OUTPUT && dir != EC_DIR_INPUT) {
+        EC_ERR("Invalid direction %u!\n", (u32) dir);
+        return -1;
+    }
+
+    sync_config = &sc->sync_configs[sync_index];
+    sync_config->dir = dir;
+    return 0;
+}
+
+/*****************************************************************************/
+
 int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
-        ec_direction_t dir, uint16_t index)
-{
-    ec_pdo_list_t *pl = &sc->pdos[dir];
+        uint8_t sync_index, uint16_t pdo_index)
+{
     ec_pdo_t *pdo;
-    
-    if (sc->master->debug_level)
-        EC_DBG("Adding Pdo 0x%04X to assignment for dir %u, config %u:%u.\n",
-                index, dir, sc->alias, sc->position);
-
-    if (!(pdo = ec_pdo_list_add_pdo(pl, dir, index)))
-        return -1;
+
+    if (sc->master->debug_level)
+        EC_DBG("ecrt_slave_config_pdo_assign_add(sc = 0x%x, sync_index = %u, "
+                "pdo_index = 0x%04X)\n", (u32) sc, sync_index, pdo_index);
+
+    if (sync_index >= EC_MAX_SYNCS) {
+        EC_ERR("Invalid sync manager index %u!\n", sync_index);
+        return -1;
+    }
+
+    if (!(pdo = ec_pdo_list_add_pdo(&sc->sync_configs[sync_index].pdos, pdo_index)))
+        return -1;
+    pdo->sync_index = sync_index;
 
     ec_slave_config_load_default_mapping(sc, pdo);
     return 0;
@@ -361,13 +400,18 @@
 /*****************************************************************************/
 
 void ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc,
-        ec_direction_t dir)
-{
-    if (sc->master->debug_level)
-        EC_DBG("Clearing Pdo assignment for dir %u, config %u:%u.\n",
-                dir, sc->alias, sc->position);
-
-    ec_pdo_list_clear_pdos(&sc->pdos[dir]);
+        uint8_t sync_index)
+{
+    if (sc->master->debug_level)
+        EC_DBG("ecrt_slave_config_pdo_assign_clear(sc = 0x%x, "
+                "sync_index = %u)\n", (u32) sc, sync_index);
+
+    if (sync_index >= EC_MAX_SYNCS) {
+        EC_ERR("Invalid sync manager index %u!\n", sync_index);
+        return;
+    }
+
+    ec_pdo_list_clear_pdos(&sc->sync_configs[sync_index].pdos);
 }
 
 /*****************************************************************************/
@@ -376,16 +420,19 @@
         uint16_t pdo_index, uint16_t entry_index, uint8_t entry_subindex,
         uint8_t entry_bit_length)
 {
-    ec_direction_t dir;
-    ec_pdo_t *pdo;
+    uint8_t sync_index;
+    ec_pdo_t *pdo = NULL;
     
     if (sc->master->debug_level)
-        EC_DBG("Adding Pdo entry 0x%04X:%02X (%u bit) to mapping of Pdo"
-                " 0x%04X, config %u:%u.\n", entry_index, entry_subindex,
-                entry_bit_length, pdo_index, sc->alias, sc->position);
-
-    for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
-        if ((pdo = ec_pdo_list_find_pdo(&sc->pdos[dir], pdo_index)))
+        EC_DBG("ecrt_slave_config_pdo_mapping_add(sc = 0x%x, "
+                "pdo_index = 0x%04X, entry_index = 0x%04X, "
+                "entry_subindex = 0x%02X, entry_bit_length = %u)\n",
+                (u32) sc, pdo_index, entry_index, entry_subindex,
+                entry_bit_length);
+
+    for (sync_index = 0; sync_index < EC_MAX_SYNCS; sync_index++)
+        if ((pdo = ec_pdo_list_find_pdo(
+                        &sc->sync_configs[sync_index].pdos, pdo_index)))
             break;
 
     if (!pdo) {
@@ -403,15 +450,16 @@
 void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
         uint16_t pdo_index)
 {
-    ec_direction_t dir;
-    ec_pdo_t *pdo;
+    uint8_t sync_index;
+    ec_pdo_t *pdo = NULL;
     
     if (sc->master->debug_level)
-        EC_DBG("Clearing mapping of Pdo 0x%04X, config %u:%u.\n",
-                pdo_index, sc->alias, sc->position);
-
-    for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
-        if ((pdo = ec_pdo_list_find_pdo(&sc->pdos[dir], pdo_index)))
+        EC_DBG("ecrt_slave_config_pdo_mapping_clear(sc = 0x%x, "
+                "pdo_index = 0x%04X)\n", (u32) sc, pdo_index);
+
+    for (sync_index = 0; sync_index < EC_MAX_SYNCS; sync_index++)
+        if ((pdo = ec_pdo_list_find_pdo(
+                        &sc->sync_configs[sync_index].pdos, pdo_index)))
             break;
 
     if (!pdo) {
@@ -425,46 +473,59 @@
 
 /*****************************************************************************/
 
-int ecrt_slave_config_pdos(ec_slave_config_t *sc, unsigned int n_infos,
-        const ec_pdo_info_t pdo_infos[])
-{
-    unsigned int i, j;
-    const ec_pdo_info_t *pi;
-    ec_pdo_list_t *pl;
-    unsigned int cleared[] = {0, 0};
-    const ec_pdo_entry_info_t *ei;
-
-    if (!pdo_infos)
+int ecrt_slave_config_sync_managers(ec_slave_config_t *sc,
+        unsigned int n_syncs, const ec_sync_info_t syncs[])
+{
+    unsigned int i, j, k;
+    const ec_sync_info_t *sync_info;
+    const ec_pdo_info_t *pdo_info;
+    const ec_pdo_entry_info_t *entry_info;
+
+    if (sc->master->debug_level)
+        EC_DBG("ecrt_slave_config_sync_managers(sc = 0x%x, n_syncs = %u, "
+                "syncs = 0x%x)\n", (u32) sc, n_syncs, (u32) syncs);
+
+    if (!syncs)
         return 0;
 
-    for (i = 0; i < n_infos; i++) {
-        pi = &pdo_infos[i];
-
-        if (pi->dir == EC_END)
+    for (i = 0; i < n_syncs; i++) {
+        sync_info = &syncs[i];
+
+        if (sync_info->index == 0xff)
             break;
 
-        pl = &sc->pdos[pi->dir];
-
-        if (!cleared[pi->dir]) {
-            ecrt_slave_config_pdo_assign_clear(sc, pi->dir);
-            cleared[pi->dir] = 1;
+        if (sync_info->index >= EC_MAX_SYNCS) {
+            EC_ERR("Invalid sync manager index %u!\n", sync_info->index);
+            return -1;
         }
 
-        if (ecrt_slave_config_pdo_assign_add(sc, pi->dir, pi->index))
+        if (ecrt_slave_config_sync_manager(
+                    sc, sync_info->index, sync_info->dir))
             return -1;
 
-        if (pi->n_entries && pi->entries) { // mapping provided
-            if (sc->master->debug_level)
-                EC_DBG("  Pdo mapping information provided.\n");
-
-            ecrt_slave_config_pdo_mapping_clear(sc, pi->index);
-
-            for (j = 0; j < pi->n_entries; j++) {
-                ei = &pi->entries[j];
-
-                if (ecrt_slave_config_pdo_mapping_add(sc, pi->index,
-                        ei->index, ei->subindex, ei->bit_length))
+        if (sync_info->n_pdos && sync_info->pdos) {
+            ecrt_slave_config_pdo_assign_clear(sc, sync_info->index);
+
+            for (j = 0; j < sync_info->n_pdos; j++) {
+                pdo_info = &sync_info->pdos[j];
+
+                if (ecrt_slave_config_pdo_assign_add(
+                            sc, sync_info->index, pdo_info->index))
                     return -1;
+
+                if (pdo_info->n_entries && pdo_info->entries) {
+                    ecrt_slave_config_pdo_mapping_clear(sc, pdo_info->index);
+
+                    for (k = 0; k < pdo_info->n_entries; k++) {
+                        entry_info = &pdo_info->entries[k];
+
+                        if (ecrt_slave_config_pdo_mapping_add(sc,
+                                    pdo_info->index, entry_info->index,
+                                    entry_info->subindex,
+                                    entry_info->bit_length))
+                            return -1;
+                    }
+                }
             }
         }
     }
@@ -482,8 +543,8 @@
         unsigned int *bit_position
         )
 {
-    ec_direction_t dir;
-    ec_pdo_list_t *pdos;
+    uint8_t sync_index;
+    const ec_sync_config_t *sync_config;
     unsigned int bit_offset, bit_pos;
     ec_pdo_t *pdo;
     ec_pdo_entry_t *entry;
@@ -492,18 +553,33 @@
     if (sc->master->debug_level)
         EC_DBG("ecrt_slave_config_reg_pdo_entry(sc = 0x%x, index = 0x%04X, "
                 "subindex = 0x%02X, domain = 0x%x, bit_position = 0x%x)\n",
-                (unsigned int) sc, index, subindex, (unsigned int) domain,
-                (unsigned int) bit_position);
-
-    for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) {
-        pdos = &sc->pdos[dir];
+                (u32) sc, index, subindex, (u32) domain, (u32) bit_position);
+
+    for (sync_index = 0; sync_index < EC_MAX_SYNCS; sync_index++) {
+        sync_config = &sc->sync_configs[sync_index];
         bit_offset = 0;
-        list_for_each_entry(pdo, &pdos->list, list) {
+
+        list_for_each_entry(pdo, &sync_config->pdos.list, list) {
             list_for_each_entry(entry, &pdo->entries, list) {
                 if (entry->index != index || entry->subindex != subindex) {
                     bit_offset += entry->bit_length;
                 } else {
-                    goto found;
+                    sync_offset = ec_slave_config_prepare_fmmu(
+                            sc, domain, sync_index, sync_config->dir);
+                    if (sync_offset < 0)
+                        return -2;
+
+                    bit_pos = bit_offset % 8;
+                    if (bit_position) {
+                        *bit_position = bit_pos;
+                    } else if (bit_pos) {
+                        EC_ERR("Pdo entry 0x%04X:%02X does not byte-align "
+                                "in config %u:%u.\n", index, subindex,
+                                sc->alias, sc->position);
+                        return -3;
+                    }
+
+                    return sync_offset + bit_offset / 8;
                 }
             }
         }
@@ -512,22 +588,6 @@
     EC_ERR("Pdo entry 0x%04X:%02X is not mapped in slave config %u:%u.\n",
            index, subindex, sc->alias, sc->position);
     return -1;
-
-found:
-    sync_offset = ec_slave_config_prepare_fmmu(sc, domain, dir);
-    if (sync_offset < 0)
-        return -2;
-
-    bit_pos = bit_offset % 8;
-    if (bit_position) {
-        *bit_position = bit_pos;
-    } else if (bit_pos) {
-        EC_ERR("Pdo entry 0x%04X:%02X does not byte-align in config %u:%u.\n",
-                index, subindex, sc->alias, sc->position);
-        return -3;
-    }
-
-    return sync_offset + bit_offset / 8;
 }
 
 
@@ -643,11 +703,12 @@
 
 /** \cond */
 
+EXPORT_SYMBOL(ecrt_slave_config_sync_manager);
 EXPORT_SYMBOL(ecrt_slave_config_pdo_assign_add);
 EXPORT_SYMBOL(ecrt_slave_config_pdo_assign_clear);
 EXPORT_SYMBOL(ecrt_slave_config_pdo_mapping_add);
 EXPORT_SYMBOL(ecrt_slave_config_pdo_mapping_clear);
-EXPORT_SYMBOL(ecrt_slave_config_pdos);
+EXPORT_SYMBOL(ecrt_slave_config_sync_managers);
 EXPORT_SYMBOL(ecrt_slave_config_reg_pdo_entry);
 EXPORT_SYMBOL(ecrt_slave_config_sdo);
 EXPORT_SYMBOL(ecrt_slave_config_sdo8);
--- a/master/slave_config.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/slave_config.h	Thu Jun 26 13:16:15 2008 +0000
@@ -47,8 +47,8 @@
 
 #include "globals.h"
 #include "slave.h"
+#include "sync_config.h"
 #include "fmmu_config.h"
-#include "pdo_list.h"
 
 /*****************************************************************************/
 
@@ -67,13 +67,14 @@
     ec_slave_t *slave; /**< Slave pointer. This is \a NULL, if the slave is
                          offline. */
 
-    ec_pdo_list_t pdos[2]; /**< Output and input Pdo assignment / mapping. */
+    ec_sync_config_t sync_configs[EC_MAX_SYNCS]; /**< Sync manager
+                                                   configurations. */
+    ec_fmmu_config_t fmmu_configs[EC_MAX_FMMUS]; /**< FMMU configurations. */
+    uint8_t used_fmmus; /**< Number of FMMUs used. */
 
     struct list_head sdo_configs; /**< List of Sdo configurations. */
     struct list_head sdo_requests; /**< List of Sdo requests. */
 
-    ec_fmmu_config_t fmmu_configs[EC_MAX_FMMUS]; /**< FMMU configurations. */
-    uint8_t used_fmmus; /**< Number of FMMUs used. */
 };
 
 /*****************************************************************************/
@@ -85,9 +86,7 @@
 int ec_slave_config_attach(ec_slave_config_t *);
 void ec_slave_config_detach(ec_slave_config_t *);
 
-void ec_slave_config_load_default_assignment(ec_slave_config_t *);
-void ec_slave_config_load_default_mapping(const ec_slave_config_t *,
-        ec_pdo_t *);
+void ec_slave_config_load_default_sync_config(ec_slave_config_t *);
 
 unsigned int ec_slave_config_sdo_count(const ec_slave_config_t *);
 const ec_sdo_request_t *ec_slave_config_get_sdo_by_pos_const(
--- a/master/sync.c	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/sync.c	Thu Jun 26 13:16:15 2008 +0000
@@ -49,13 +49,14 @@
  */
 void ec_sync_init(
         ec_sync_t *sync, /**< EtherCAT sync manager. */
-        ec_slave_t *slave, /**< EtherCAT slave. */
-        unsigned int index /**< Sync manager index. */
+        ec_slave_t *slave /**< EtherCAT slave. */
         )
 {
     sync->slave = slave;
-    sync->index = index;    
-
+    sync->physical_start_address = 0x0000;
+    sync->default_length = 0x0000;
+    sync->control_register = 0x00;
+    sync->enable = 0x00;
     ec_pdo_list_init(&sync->pdos);
     sync->assign_source = EC_ASSIGN_NONE;
 }
@@ -70,15 +71,12 @@
         )
 {
    sync->slave = other->slave;
-   sync->index = other->index;
    sync->physical_start_address = other->physical_start_address;
-   sync->length = other->length;
+   sync->default_length = other->default_length;
    sync->control_register = other->control_register;
    sync->enable = other->enable;
-   
    ec_pdo_list_init(&sync->pdos);
    ec_pdo_list_copy(&sync->pdos, &other->pdos);
-
    sync->assign_source = other->assign_source;
 }
 
@@ -95,28 +93,37 @@
 
 /*****************************************************************************/
 
-/** Initializes a sync manager configuration page with SII data.
+/** Initializes a sync manager configuration page.
  *
  * The referenced memory (\a data) must be at least \a EC_SYNC_SIZE bytes.
  */
-void ec_sync_config(
+void ec_sync_page(
         const ec_sync_t *sync, /**< Sync manager. */
+        uint8_t sync_index, /**< Index of the sync manager. */
         uint16_t data_size, /**< Data size. */
+        ec_direction_t dir, /**< Direction (overrides the control byte,
+                              if set to EC_DIR_INPUT or EC_DIR_OUTPUT). */
         uint8_t *data /**> Configuration memory. */
         )
 {
     // enable only if SII enable is set and size is > 0.
     uint16_t enable = sync->enable && data_size;
+    uint8_t control = sync->control_register;
 
-    if (sync->slave->master->debug_level) {
+    if (dir == EC_DIR_OUTPUT || dir == EC_DIR_INPUT) {
+        // override sync manager direction bits with dir parameter
+        EC_WRITE_BIT(&control, 2, dir == EC_DIR_OUTPUT ? 1 : 0);
+        EC_WRITE_BIT(&control, 3, 0);
+    }
+
+    if (sync->slave->master->debug_level)
         EC_DBG("SM%u: Addr 0x%04X, Size %3u, Ctrl 0x%02X, En %u\n",
-               sync->index, sync->physical_start_address,
-               data_size, sync->control_register, enable);
-    }
+               sync_index, sync->physical_start_address,
+               data_size, control, enable);
 
     EC_WRITE_U16(data,     sync->physical_start_address);
     EC_WRITE_U16(data + 2, data_size);
-    EC_WRITE_U8 (data + 4, sync->control_register);
+    EC_WRITE_U8 (data + 4, control);
     EC_WRITE_U8 (data + 5, 0x00); // status byte (read only)
     EC_WRITE_U16(data + 6, enable);
 }
@@ -137,35 +144,17 @@
 
 /*****************************************************************************/
 
-/** Get direction covered by sync manager.
- *
- * \return Direction covered by the given sync manager.
+/** Determines the default direction from the control register.
  */
-ec_direction_t ec_sync_direction(
+ec_direction_t ec_sync_default_direction(
         const ec_sync_t *sync /**< EtherCAT sync manager. */
         )
 {
-    int index = sync->index;
-
-    if (sync->slave->sii.sync_count != 1) {
-        if (sync->slave && sync->slave->sii.mailbox_protocols) {
-            index -= 2;
-        }
-
-        if (index < 0 || index > 1) {
-            EC_WARN("ec_sync_get_direction(): invalid sync manager index.\n");
-            return EC_DIR_OUTPUT;
-        }
-    } else { // sync_count == 1
-        if (!list_empty(&sync->pdos.list)) {
-            const ec_pdo_t *pdo =
-                list_entry(sync->pdos.list.next, ec_pdo_t, list);
-            return pdo->dir;
-        }
-        
+    switch ((sync->control_register & 0x0C) >> 2) {
+        case 0x0: return EC_DIR_INPUT;
+        case 0x1: return EC_DIR_INPUT;
+        default: return EC_DIR_INVALID;
     }
-
-    return (ec_direction_t) index;
 }
 
 /*****************************************************************************/
--- a/master/sync.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/master/sync.h	Thu Jun 26 13:16:15 2008 +0000
@@ -40,8 +40,6 @@
 #ifndef __EC_SYNC_H__
 #define __EC_SYNC_H__
 
-#include <linux/list.h>
-
 #include "../include/ecrt.h"
 
 #include "globals.h"
@@ -64,9 +62,8 @@
  */
 typedef struct {
     ec_slave_t *slave; /**< Slave, the sync manager belongs to. */
-    unsigned int index; /**< Sync manager index. */
     uint16_t physical_start_address; /**< Physical start address. */
-    uint16_t length; /**< Data length in bytes. */
+    uint16_t default_length; /**< Data length in bytes. */
     uint8_t control_register; /**< Control register value. */
     uint8_t enable; /**< Enable bit. */
     ec_pdo_list_t pdos; /**< Current Pdo assignment. */
@@ -75,15 +72,13 @@
 
 /*****************************************************************************/
 
-void ec_sync_init(ec_sync_t *, ec_slave_t *, unsigned int);
+void ec_sync_init(ec_sync_t *, ec_slave_t *);
 void ec_sync_init_copy(ec_sync_t *, const ec_sync_t *);
 void ec_sync_clear(ec_sync_t *);
-
-void ec_sync_config(const ec_sync_t *, uint16_t, uint8_t *);
-
+void ec_sync_page(const ec_sync_t *, uint8_t, uint16_t, ec_direction_t,
+        uint8_t *);
 int ec_sync_add_pdo(ec_sync_t *, const ec_pdo_t *);
-
-ec_direction_t ec_sync_direction(const ec_sync_t *);
+ec_direction_t ec_sync_default_direction(const ec_sync_t *);
 
 /*****************************************************************************/
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/sync_config.c	Thu Jun 26 13:16:15 2008 +0000
@@ -0,0 +1,66 @@
+/******************************************************************************
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
+ *
+ *  This file is part of the IgH EtherCAT Master.
+ *
+ *  The IgH EtherCAT Master is free software; you can redistribute it
+ *  and/or modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2 of the
+ *  License, or (at your option) any later version.
+ *
+ *  The IgH EtherCAT Master is distributed in the hope that it will be
+ *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with the IgH EtherCAT Master; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  The right to use EtherCAT Technology is granted and comes free of
+ *  charge under condition of compatibility of product made by
+ *  Licensee. People intending to distribute/sell products based on the
+ *  code, have to sign an agreement to guarantee that products using
+ *  software based on IgH EtherCAT master stay compatible with the actual
+ *  EtherCAT specification (which are released themselves as an open
+ *  standard) as the (only) precondition to have the right to use EtherCAT
+ *  Technology, IP and trade marks.
+ *
+ *****************************************************************************/
+
+/** \file
+ * EtherCAT sync manager configuration methods.
+ */
+
+/*****************************************************************************/
+
+#include "globals.h"
+#include "sync_config.h"
+
+/*****************************************************************************/
+
+/** Constructor.
+ */
+void ec_sync_config_init(
+        ec_sync_config_t *sync_config /**< Sync manager configuration. */
+        )
+{
+    sync_config->dir = EC_DIR_INVALID;
+    ec_pdo_list_init(&sync_config->pdos);
+}
+
+/*****************************************************************************/
+
+/** Destructor.
+ */
+void ec_sync_config_clear(
+        ec_sync_config_t *sync_config /**< Sync manager configuration. */
+        )
+{
+    ec_pdo_list_clear(&sync_config->pdos);
+}
+
+/*****************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/sync_config.h	Thu Jun 26 13:16:15 2008 +0000
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
+ *
+ *  This file is part of the IgH EtherCAT Master.
+ *
+ *  The IgH EtherCAT Master is free software; you can redistribute it
+ *  and/or modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2 of the
+ *  License, or (at your option) any later version.
+ *
+ *  The IgH EtherCAT Master is distributed in the hope that it will be
+ *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with the IgH EtherCAT Master; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  The right to use EtherCAT Technology is granted and comes free of
+ *  charge under condition of compatibility of product made by
+ *  Licensee. People intending to distribute/sell products based on the
+ *  code, have to sign an agreement to guarantee that products using
+ *  software based on IgH EtherCAT master stay compatible with the actual
+ *  EtherCAT specification (which are released themselves as an open
+ *  standard) as the (only) precondition to have the right to use EtherCAT
+ *  Technology, IP and trade marks.
+ *
+ *****************************************************************************/
+
+/** \file
+ * EtherCAT sync manager.
+ */
+
+/*****************************************************************************/
+
+#ifndef __EC_SYNC_CONFIG_H__
+#define __EC_SYNC_CONFIG_H__
+
+#include "../include/ecrt.h"
+
+#include "globals.h"
+#include "pdo_list.h"
+
+/*****************************************************************************/
+
+/** Sync manager configuration.
+ */
+typedef struct {
+    ec_direction_t dir; /**< Sync manager direction. */
+    ec_pdo_list_t pdos; /**< Current Pdo assignment. */
+} ec_sync_config_t;
+
+/*****************************************************************************/
+
+void ec_sync_config_init(ec_sync_config_t *);
+void ec_sync_config_clear(ec_sync_config_t *);
+
+/*****************************************************************************/
+
+#endif
--- a/tools/Master.cpp	Tue Jun 24 10:55:40 2008 +0000
+++ b/tools/Master.cpp	Thu Jun 26 13:16:15 2008 +0000
@@ -200,11 +200,12 @@
             << hex << setw(8) << config.product_code << endl
             << "Attached: " << (config.attached ? "yes" : "no") << endl;
 
-        for (j = 0; j < 2; j++) {
-            if (config.pdo_count[j]) {
-                cout << (j ? "Input" : "Output")
-                    << " Pdo assignment / mapping " << endl;
-                for (k = 0; k < config.pdo_count[j]; k++) {
+        for (j = 0; j < 16; j++) {
+            if (config.syncs[j].pdo_count) {
+                cout << "SM" << dec << j << " ("
+                    << (config.syncs[j].dir == EC_DIR_INPUT
+                            ? "Input" : "Output") << ")" << endl;
+                for (k = 0; k < config.syncs[j].pdo_count; k++) {
                     getConfigPdo(&pdo, i, j, k);
 
                     cout << "  Pdo 0x"
@@ -1190,7 +1191,7 @@
         cout << "  SlaveConfig "
             << fmmu.slave_config_alias << ":" << fmmu.slave_config_position
             << ", Dir "
-            << setfill(' ') << setw(3) << (fmmu.fmmu_dir ? "In" : "Out")
+            << setfill(' ') << setw(3) << (fmmu.dir == EC_DIR_INPUT ? "In" : "Out")
             << ", LogAddr 0x" 
             << hex << setfill('0') << setw(8) << fmmu.logical_address
             << ", Size " << dec << fmmu.data_size << endl;
@@ -1250,7 +1251,8 @@
         for (j = 0; j < sync.pdo_count; j++) {
             getPdo(&pdo, slavePosition, i, j);
 
-            cout << "  " << (pdo.dir ? "T" : "R") << "xPdo 0x"
+            cout << "  " << (sync.control_register & 0x04 ? "R" : "T")
+                << "xPdo 0x"
                 << hex << setfill('0') << setw(4) << pdo.index
                 << " \"" << pdo.name << "\"" << endl;
 
@@ -1423,6 +1425,7 @@
     ec_ioctl_slave_t slave;
     ec_ioctl_sync_t sync;
     ec_ioctl_pdo_t pdo;
+    string pdoType;
     ec_ioctl_pdo_entry_t entry;
     unsigned int i, j, k;
     
@@ -1449,9 +1452,11 @@
 
         for (j = 0; j < sync.pdo_count; j++) {
             getPdo(&pdo, slavePosition, i, j);
+            pdoType = (sync.control_register & 0x04 ? "R" : "T");
+            pdoType += "xPdo";
 
             cout
-                << "          <" << (pdo.dir ? "T" : "R") << "xPdo>" << endl
+                << "          <" << pdoType << ">" << endl
                 << "            <Index>#x"
                 << hex << setfill('0') << setw(4) << pdo.index
                 << "</Index>" << endl
@@ -1503,7 +1508,7 @@
             }
 
             cout
-                << "          </" << (pdo.dir ? "T" : "R") << "xPdo>" << endl;
+                << "          </" << pdoType << ">" << endl;
         }
     }
 
@@ -1553,12 +1558,12 @@
 void Master::getConfigPdo(
         ec_ioctl_config_pdo_t *data,
         unsigned int index,
-        unsigned int dir,
-        unsigned int pdo_pos
+        uint8_t sync_index,
+        uint16_t pdo_pos
         )
 {
     data->config_index = index;
-    data->direction = dir;
+    data->sync_index = sync_index;
     data->pdo_pos = pdo_pos;
 
     if (ioctl(fd, EC_IOCTL_CONFIG_PDO, data) < 0) {
@@ -1573,13 +1578,13 @@
 void Master::getConfigPdoEntry(
         ec_ioctl_config_pdo_entry_t *data,
         unsigned int index,
-        unsigned int dir,
-        unsigned int pdo_pos,
-        unsigned int entry_pos
+        uint8_t sync_index,
+        uint16_t pdo_pos,
+        uint8_t entry_pos
         )
 {
     data->config_index = index;
-    data->direction = dir;
+    data->sync_index = sync_index;
     data->pdo_pos = pdo_pos;
     data->entry_pos = entry_pos;
 
--- a/tools/Master.h	Tue Jun 24 10:55:40 2008 +0000
+++ b/tools/Master.h	Thu Jun 26 13:16:15 2008 +0000
@@ -12,6 +12,7 @@
 #include <vector>
 using namespace std;
 
+#include "../include/ecrt.h"
 #include "../master/ioctl.h"
 
 /****************************************************************************/
@@ -73,10 +74,10 @@
         unsigned int slaveCount();
         void getMaster(ec_ioctl_master_t *);
         void getConfig(ec_ioctl_config_t *, unsigned int);
-        void getConfigPdo(ec_ioctl_config_pdo_t *, unsigned int,
-                unsigned int, unsigned int);
+        void getConfigPdo(ec_ioctl_config_pdo_t *, unsigned int, uint8_t,
+                uint16_t);
         void getConfigPdoEntry(ec_ioctl_config_pdo_entry_t *, unsigned int,
-                unsigned int, unsigned int, unsigned int);
+                uint8_t, uint16_t, uint8_t);
         void getConfigSdo(ec_ioctl_config_sdo_t *, unsigned int, unsigned int);
         void getDomain(ec_ioctl_domain_t *, unsigned int);
         void getFmmu(ec_ioctl_domain_fmmu_t *, unsigned int, unsigned int);