Changed terms "Pdo mapping" -> "Pdo assignment" and "Pdo configuration"
authorFlorian Pose <fp@igh-essen.com>
Thu, 03 Apr 2008 13:34:13 +0000
changeset 879 9b395c5646ab
parent 878 40c379697ebf
child 880 f6212c54a5e3
Changed terms "Pdo mapping" -> "Pdo assignment" and "Pdo configuration"
-> "Pdo mapping"; created ecrt_slave_config_pdo_assign_clear() and
ecrt_slave_config_pdo_mapping_clear().
documentation/graphs/Makefile
documentation/graphs/fsm_pdo_assign.dot
documentation/graphs/fsm_pdo_config.dot
documentation/graphs/fsm_pdo_mapping.dot
documentation/graphs/fsm_slave_conf.dot
examples/mini/mini.c
include/ecrt.h
master/Kbuild.in
master/Makefile.am
master/fmmu_config.c
master/fsm_coe_map.c
master/fsm_coe_map.h
master/fsm_pdo_assign.c
master/fsm_pdo_assign.h
master/fsm_pdo_config.c
master/fsm_pdo_config.h
master/fsm_pdo_mapping.c
master/fsm_pdo_mapping.h
master/fsm_slave_config.c
master/fsm_slave_config.h
master/fsm_slave_scan.h
master/master.c
master/pdo_list.c
master/pdo_list.h
master/pdo_mapping.c
master/pdo_mapping.h
master/slave.c
master/slave_config.c
master/slave_config.h
master/sync.c
master/sync.h
--- a/documentation/graphs/Makefile	Mon Mar 31 09:42:37 2008 +0000
+++ b/documentation/graphs/Makefile	Thu Apr 03 13:34:13 2008 +0000
@@ -5,12 +5,12 @@
 #-----------------------------------------------------------------------------
 
 GRAPHS := \
+	fsm_coe_map \
+	fsm_master \
+	fsm_pdo_assign \
+	fsm_pdo_mapping \
 	fsm_slave_conf \
-	fsm_slave_scan \
-	fsm_pdo_mapping \
-	fsm_pdo_config \
-	fsm_master \
-	fsm_coe_map
+	fsm_slave_scan
 
 #-----------------------------------------------------------------------------
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/documentation/graphs/fsm_pdo_assign.dot	Thu Apr 03 13:34:13 2008 +0000
@@ -0,0 +1,19 @@
+
+/* $Id$ */
+
+digraph pdomapping {
+    size="7,9"
+    center=1
+	ratio=fill
+
+    next_sync [shape=point,label=""]
+
+    start -> next_sync [label="First SM"]
+    next_sync -> end [label="No more SMs"]
+    next_sync -> zero_count [label="Next SM"]
+    zero_count -> next_sync [label="No Pdos"]
+    zero_count -> add_pdo [label="Map first Pdo", weight=5]
+    add_pdo -> add_pdo [label="Map next Pdo"]
+    add_pdo -> pdo_count [label="No more Pdos", weight=5]
+    pdo_count -> next_sync
+}
--- a/documentation/graphs/fsm_pdo_config.dot	Mon Mar 31 09:42:37 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-
-/* $Id$ */
-
-digraph pdoconfig {
-    size="7,9"
-    center=1
-	ratio=fill
-
-    next_pdo [shape=point,label=""]
-
-    start -> next_pdo [label="First Pdo"]
-    next_pdo -> end [label="No more Pdos"]
-    next_pdo -> zero_count [label="Next Pdo"]
-    zero_count -> next_pdo [label="No Entries"]
-    zero_count -> add_entry [label="Add first entry", weight=5]
-    add_entry -> add_entry [label="Add next entry"]
-    add_entry -> entry_count [label="No more Entries", weight=5]
-    entry_count -> next_pdo
-}
--- a/documentation/graphs/fsm_pdo_mapping.dot	Mon Mar 31 09:42:37 2008 +0000
+++ b/documentation/graphs/fsm_pdo_mapping.dot	Thu Apr 03 13:34:13 2008 +0000
@@ -1,19 +1,19 @@
 
 /* $Id$ */
 
-digraph pdomapping {
+digraph pdoconfig {
     size="7,9"
     center=1
 	ratio=fill
 
-    next_sync [shape=point,label=""]
+    next_pdo [shape=point,label=""]
 
-    start -> next_sync [label="First SM"]
-    next_sync -> end [label="No more SMs"]
-    next_sync -> zero_count [label="Next SM"]
-    zero_count -> next_sync [label="No Pdos"]
-    zero_count -> add_pdo [label="Map first Pdo", weight=5]
-    add_pdo -> add_pdo [label="Map next Pdo"]
-    add_pdo -> pdo_count [label="No more Pdos", weight=5]
-    pdo_count -> next_sync
+    start -> next_pdo [label="First Pdo"]
+    next_pdo -> end [label="No more Pdos"]
+    next_pdo -> zero_count [label="Next Pdo"]
+    zero_count -> next_pdo [label="No Entries"]
+    zero_count -> add_entry [label="Add first entry", weight=5]
+    add_entry -> add_entry [label="Add next entry"]
+    add_entry -> entry_count [label="No more Entries", weight=5]
+    entry_count -> next_pdo
 }
--- a/documentation/graphs/fsm_slave_conf.dot	Mon Mar 31 09:42:37 2008 +0000
+++ b/documentation/graphs/fsm_slave_conf.dot	Thu Apr 03 13:34:13 2008 +0000
@@ -9,7 +9,7 @@
     enter_mbox_sync [shape=point,label=""]
     enter_fmmu [shape=point,label=""]
     enter_sdo_conf [shape=point,label=""]
-    enter_mapping [shape=point,label=""]
+    enter_pdo_assign [shape=point,label=""]
     enter_pdo_sync [shape=point,label=""]
     enter_safeop [shape=point,label=""]
 
@@ -32,18 +32,18 @@
     preop -> end [label="PREOP req."]
     preop -> enter_sdo_conf [weight=10]
     enter_sdo_conf -> enter_safeop [label="No configuration"]
-    enter_sdo_conf -> enter_mapping [label="No Sdo configs"]
+    enter_sdo_conf -> enter_pdo_assign [label="No Sdo configs"]
     enter_sdo_conf -> sdo_conf [label="Sdo configs", weight=10]
     sdo_conf -> sdo_conf
     sdo_conf -> error
-    sdo_conf -> enter_mapping [weight=10]
-    enter_mapping -> mapping [weight=10]
-    mapping -> mapping
-    mapping -> error
-    mapping -> pdo_conf [weight=10]
-    pdo_conf -> pdo_conf
-    pdo_conf -> error
-    pdo_conf -> enter_pdo_sync [weight=10]
+    sdo_conf -> enter_pdo_assign [weight=10]
+    enter_pdo_assign -> pdo_assign [weight=10]
+    pdo_assign -> pdo_assign
+    pdo_assign -> error
+    pdo_assign -> pdo_mapping [weight=10]
+    pdo_mapping -> pdo_mapping
+    pdo_mapping -> error
+    pdo_mapping -> enter_pdo_sync [weight=10]
     enter_pdo_sync -> pdo_sync [label="Pdo SMs", weight=10]
     enter_pdo_sync -> enter_fmmu
     pdo_sync -> pdo_sync
--- a/examples/mini/mini.c	Mon Mar 31 09:42:37 2008 +0000
+++ b/examples/mini/mini.c	Thu Apr 03 13:34:13 2008 +0000
@@ -45,7 +45,7 @@
 #define FREQUENCY 100
 
 // Optional features
-#define CONFIGURE_MAPPING
+#define CONFIGURE_PDOS
 #define EXTERNAL_MEMORY
 #define SDO_ACCESS
 
@@ -82,7 +82,7 @@
 
 /*****************************************************************************/
 
-#ifdef CONFIGURE_MAPPING
+#ifdef CONFIGURE_PDOS
 static ec_pdo_entry_info_t el3162_channel1[] = {
     {0x3101, 1,  8}, // status
     {0x3101, 2, 16}  // value
@@ -93,10 +93,10 @@
     {0x3102, 2, 16}  // value
 };
 
-static ec_pdo_info_t el3162_mapping[] = {
+static ec_pdo_info_t el3162_pdos[] = {
     {EC_DIR_INPUT, 0x1A00, 2, el3162_channel1},
     {EC_DIR_INPUT, 0x1A01, 2, el3162_channel2},
-    {EC_MAP_END}
+    {EC_END}
 };
 
 static ec_pdo_entry_info_t el2004_channels[] = {
@@ -106,7 +106,7 @@
     {0x3001, 4, 1}  // Value 4
 };
 
-static ec_pdo_info_t el2004_mapping[] = {
+static ec_pdo_info_t el2004_pdos[] = {
     {EC_DIR_OUTPUT, 0x1600, 1, &el2004_channels[0]},
     {EC_DIR_OUTPUT, 0x1601, 1, &el2004_channels[1]},
     {EC_DIR_OUTPUT, 0x1602, 1, &el2004_channels[2]},
@@ -251,7 +251,7 @@
 
 int __init init_mini_module(void)
 {
-#ifdef CONFIGURE_MAPPING
+#ifdef CONFIGURE_PDOS
     ec_slave_config_t *sc;
 #endif
 #ifdef EXTERNAL_MEMORY
@@ -273,15 +273,15 @@
         goto out_release_master;
     }
 
-#ifdef CONFIGURE_MAPPING
-    printk(KERN_INFO PFX "Configuring Pdo mapping...\n");
+#ifdef CONFIGURE_PDOS
+    printk(KERN_INFO PFX "Configuring Pdos...\n");
     if (!(sc = ecrt_master_slave_config(master, 0, 1, Beckhoff_EL3162))) {
         printk(KERN_ERR PFX "Failed to get slave configuration.\n");
         goto out_release_master;
     }
 
-    if (ecrt_slave_config_mapping(sc, EC_MAP_END, el3162_mapping)) {
-        printk(KERN_ERR PFX "Failed to configure Pdo mapping.\n");
+    if (ecrt_slave_config_pdos(sc, EC_END, el3162_pdos)) {
+        printk(KERN_ERR PFX "Failed to configure Pdos.\n");
         goto out_release_master;
     }
 
@@ -290,8 +290,8 @@
         goto out_release_master;
     }
 
-    if (ecrt_slave_config_mapping(sc, 4, el2004_mapping)) {
-        printk(KERN_ERR PFX "Failed to configure Pdo mapping.\n");
+    if (ecrt_slave_config_pdos(sc, 4, el2004_pdos)) {
+        printk(KERN_ERR PFX "Failed to configure Pdos.\n");
         goto out_release_master;
     }
 #endif
--- a/include/ecrt.h	Mon Mar 31 09:42:37 2008 +0000
+++ b/include/ecrt.h	Thu Apr 03 13:34:13 2008 +0000
@@ -37,10 +37,10 @@
  *
  * \defgroup RealtimeInterface EtherCAT Realtime Interface
  *
- * EtherCAT interface for realtime modules. This interface is designed for
- * realtime modules that want to use EtherCAT. There are functions to request
- * a master, to map process data, to communicate with slaves via CoE and to
- * configure and activate the bus.
+ * EtherCAT interface for realtime applications. This interface is designed
+ * for realtime modules that want to use EtherCAT. There are functions to
+ * request a master, to map process data, to communicate with slaves via CoE
+ * and to configure and activate the bus.
  *
  * Changes in Version 1.4:
  *
@@ -64,11 +64,12 @@
  *   is directly usable. If the domain's process data is allocated internally,
  *   the start address can be retrieved with ecrt_domain_data().
  * - Replaced ecrt_slave_pdo_mapping/add/clear() with
- *   ecrt_slave_config_pdo() to add a Pdo to the mapping and
- *   ecrt_slave_config_pdo_entry() to add a Pdo entry to a Pdo configuration.
- *   ecrt_slave_config_mapping() is a convenience function for
- *   both, that uses the new data types ec_pdo_info_t and ec_pdo_entry_info_t.
- *   Mapped Pdo entries can now immediately be registered.
+ *   ecrt_slave_config_pdo_assign_add() to add a Pdo to a sync manager's Pdo
+ *   assignment and ecrt_slave_config_pdo_mapping_add() to add a Pdo entry to a
+ *   Pdo's mapping. ecrt_slave_config_pdos() is a convenience function
+ *   for both, that uses the new data types ec_pdo_info_t and
+ *   ec_pdo_entry_info_t. Pdo entries, that are mapped with these functions
+ *   can now immediately be registered, even if the bus is offline.
  * - Renamed ec_bus_status_t, ec_master_status_t to ec_bus_state_t and
  *   ec_master_state_t, respectively. Renamed ecrt_master_get_status() to
  *   ecrt_master_state(), for consistency reasons.
@@ -122,11 +123,11 @@
 
 /*****************************************************************************/
 
-/** End of mapping.
- *
- * This is used in ecrt_slave_config_mapping().
- */
-#define EC_MAP_END ~0U
+/** End of the Pdo list.
+ *
+ * This is used in ecrt_slave_config_pdos().
+ */
+#define EC_END ~0U
 
 /******************************************************************************
  * Data types 
@@ -149,6 +150,9 @@
 /** Bus state.
  *
  * This is used in ec_master_state_t.
+ *
+ * \deprecated
+ * \todo remove
  */
 typedef enum {
     EC_BUS_FAILURE = -1, /**< At least one configured slave is offline. */
@@ -214,9 +218,10 @@
 
 /*****************************************************************************/
 
-/** Pdo entry mapping.
- *
- * \see ecrt_slave_config_mapping().
+/** Pdo entry information.
+ *
+ * This can be used to map multiple Pdo entries into a given Pdo using
+ * ecrt_slave_config_pdos().
  */
 typedef struct {
     uint16_t index; /**< Index of the Pdo entry to add to the Pdo
@@ -230,17 +235,17 @@
 
 /** Pdo information.
  *
- * \see ecrt_slave_config_mapping().
+ * This can be use to assign multiple Pdos to a sync manager using
+ * ecrt_slave_config_pdos().
  */
 typedef struct {
     ec_direction_t dir; /**< Pdo direction (input/output). */
     uint16_t index; /**< Index of the Pdo to map. */
-    unsigned int n_entries; /**< Number of Pdo entries for the Pdo
-                              configuration. Zero means, that the default Pdo
-                              configuration shall be used. */
-    ec_pdo_entry_info_t *entries; /**< Pdo configuration array. This
-                                    array must contain at least \a
-                                    n_entries values. */
+    unsigned int n_entries; /**< Number of Pdo entries in \a entries to map.
+                              Zero means, that the default mapping shall be
+                              used. */
+    ec_pdo_entry_info_t *entries; /**< Array of Pdo entries to map. This must
+                                    contain at least \a n_entries values. */
 } ec_pdo_info_t;
 
 /*****************************************************************************/
@@ -358,27 +363,38 @@
         uint32_t product_code /**< Expected product code. */
         );
 
-/** Applies the bus configuration and switches to realtime mode.
- *
- * Does the complete configuration and activation for all slaves. Sets sync
- * managers and FMMUs, and does the appropriate transitions, until the slave
- * is operational.
+/** Finishes the configuration phase and prepares for realtime mode.
+ *
+ * This function has to be called after all Pdo entries are registered. It
+ * tells the master that the configuration phase is finished and the realtime
+ * operation will begin. The function allocates internal memory for the
+ * domains and calculates the logical FMMU addresses for domain members. It
+ * tells the master state machine that the bus configuration is now to be
+ * applied.
+ *
+ * \attention After this function has been called, the realtime application is
+ * in charge of cyclically calling ecrt_master_send() and
+ * ecrt_master_receive() to ensure bus communication. Before calling this
+ * function, the master thread is responsible for that, so these functions may
+ * not be called!
  *
  * \return 0 in case of success, else < 0
  */
-int ecrt_master_activate(
-        ec_master_t *master /**< EtherCAT master. */
-        );
+int ecrt_master_activate( ec_master_t *master /**< EtherCAT master. */);
 
 /** Sends all datagrams in the queue.
  *
- * \todo doc
+ * This has to be called cyclically by the realtime application after
+ * ecrt_master_activate() has returned.
  */
 void ecrt_master_send(
         ec_master_t *master /**< EtherCAT master. */
         );
 
 /** Fetches received frames from the hardware and processes the datagrams.
+ *
+ * This has to be called cyclically by the realtime application after
+ * ecrt_master_activate() has returned.
  */
 void ecrt_master_receive(
         ec_master_t *master /**< EtherCAT master. */
@@ -397,48 +413,64 @@
  * Slave configuration methods
  *****************************************************************************/
 
-/** Add a Pdo to the slave's Pdo mapping for the given direction.
- *
- * The first call of this function for a given \a dir will clear the default
- * mapping.
- *
- * \see ecrt_slave_config_mapping()
+/** Add a Pdo to a sync manager's Pdo assignment.
+ *
+ * \see ecrt_slave_config_pdos()
  * \return zero on success, else non-zero
  */
-int ecrt_slave_config_pdo(
+int ecrt_slave_config_pdo_assign_add(
         ec_slave_config_t *sc, /**< Slave configuration. */
-        ec_direction_t dir, /**< Pdo direction (input/output). */
-        uint16_t index /**< Index of the Pdo to map. */
-        );
-
-/** Add a Pdo entry to the given Pdo's configuration.
- *
- * The first call of this function for a given \a pdo_index will clear the
- * default Pdo configuration.
- *
- * \see ecrt_slave_config_mapping()
+        ec_direction_t dir, /**< Sync manager direction (input/output). */
+        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.
+ */
+void ecrt_slave_config_pdo_assign_clear(
+        ec_slave_config_t *sc, /**< Slave configuration. */
+        ec_direction_t dir /**< Sync manager direction (input/output). */
+        );
+
+/** Add a Pdo entry to the given Pdo's mapping.
+ *
+ * \see ecrt_slave_config_pdos()
  * \return zero on success, else non-zero
  */
-int ecrt_slave_config_pdo_entry(
+int ecrt_slave_config_pdo_mapping_add(
         ec_slave_config_t *sc, /**< Slave configuration. */
-        uint16_t pdo_index, /**< Index of the Pdo to configure. */
+        uint16_t pdo_index, /**< Index of the Pdo. */
         uint16_t entry_index, /**< Index of the Pdo entry to add to the Pdo's
-                                configuration. */
+                                mapping. */
         uint8_t entry_subindex, /**< Subindex of the Pdo entry to add to the
-                                  Pdo's configuration. */
+                                  Pdo's mapping. */
         uint8_t entry_bit_length /**< Size of the Pdo entry in bit. */
         );
 
-/** Specify the Pdo mapping and (optionally) the Pdo configuration.
- *
- * This function is a convenience function for the ecrt_slave_config_pdo()
- * and ecrt_slave_config_pdo_entry() functions, that are better suitable
- * for automatic code generation.
- *
- * The following example shows, how to specify a complete Pdo mapping
- * including the Pdo configuration. With this information, the master is able
- * to reserve the complete process data, even if the slave is not present
- * at configuration time:
+/** Clear the mapping of a given Pdo.
+ *
+ * This can be called before mapping Pdo entries via
+ * ecrt_slave_config_pdo_mapping_add(), to clear the default mapping.
+ */
+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.
+ *
+ * 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
+ * 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:
  *
  * \code
  * const ec_pdo_entry_info_t el3162_channel1[] = {
@@ -451,52 +483,52 @@
  *     {0x3102, 2, 16}  // value
  * };
  * 
- * const ec_pdo_info_t el3162_mapping[] = {
+ * const ec_pdo_info_t el3162_pdos[] = {
  *     {EC_DIR_INPUT, 0x1A00, 2, el3162_channel1},
  *     {EC_DIR_INPUT, 0x1A01, 2, el3162_channel2},
  * };
  * 
- * if (ecrt_slave_config_mapping(sc, 2, el3162_mapping))
+ * if (ecrt_slave_config_pdos(sc, 2, el3162_pdos))
  *     return -1; // error
  * \endcode
- *
- * The next example shows, how to configure only the Pdo mapping. The entries
- * for each mapped Pdo are taken from the default Pdo configuration. Please
- * note, that Pdo entry registration will fail, if the Pdo configuration is
- * left empty and the slave is offline.
+ * 
+ * The next example shows, how to configure only the Pdo assignment. 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 pdo_mapping[] = {
+ * const ec_pdo_info_t pdos[] = {
  *     {EC_DIR_INPUT, 0x1600}, // Channel 1
  *     {EC_DIR_INPUT, 0x1601}  // Channel 2
  * };
  * 
- * if (ecrt_slave_config_mapping(slave_config_ana_in, 2, pdo_mapping))
+ * if (ecrt_slave_config_pdos(slave_config_ana_in, 2, pdos))
  *     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_MAP_END. In this case,
+ * - 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;
- *   using EC_MAP_END is recommended.
+ *   using EC_END is recommended.
  *
  * \return zero on success, else non-zero
  */
-int ecrt_slave_config_mapping(
+int ecrt_slave_config_pdos(
         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 Pdo mapping. */
+        const ec_pdo_info_t pdo_infos[] /**< List with Pdos. */
         );
 
 /** Registers a Pdo entry for process data exchange in a domain.
  *
- * Searches the current mapping and Pdo configurations for the given Pdo
+ * Searches the current Pdo assignment and Pdo mappings for the given Pdo
  * entry. An error is raised, if the given entry is not mapped. Otherwise, the
  * corresponding sync manager and FMMU configurations are provided for slave
- * configuration and the respective sync manager's Pdos are appended to the
- * given domain, if not already done. The offset of the requested Pdo entry's
- * data inside the domain's process data is returned.
+ * configuration and the respective sync manager's assigned Pdos are appended
+ * to the given domain, if not already done. The offset of the requested Pdo
+ * entry's data inside the domain's process data is returned.
  *
  * \retval >=0 Success: Offset of the Pdo entry's process data.
  * \retval -1  Error: Pdo entry not found.
--- a/master/Kbuild.in	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/Kbuild.in	Thu Apr 03 13:34:13 2008 +0000
@@ -42,7 +42,7 @@
     fsm_coe.o \
     fsm_coe_map.o \
     fsm_master.o \
-    fsm_pdo_config.o \
+    fsm_pdo_assign.o \
     fsm_pdo_mapping.o \
     fsm_sii.o \
     fsm_slave_config.o \
@@ -51,7 +51,7 @@
     master.o \
     module.o \
     pdo.o \
-    pdo_mapping.o \
+    pdo_list.o \
     sdo.o \
     sdo_entry.o \
     sdo_request.o \
--- a/master/Makefile.am	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/Makefile.am	Thu Apr 03 13:34:13 2008 +0000
@@ -44,7 +44,7 @@
 	fsm_coe.c fsm_coe.h \
 	fsm_coe_map.c fsm_coe_map.h \
 	fsm_master.c fsm_master.h \
-	fsm_pdo_config.c fsm_pdo_config.h \
+	fsm_pdo_assign.c fsm_pdo_assign.h \
 	fsm_pdo_mapping.c fsm_pdo_mapping.h \
 	fsm_sii.c fsm_sii.h \
 	fsm_slave_config.c fsm_slave_config.h \
@@ -54,7 +54,7 @@
 	master.c master.h \
 	module.c \
 	pdo.c pdo.h \
-	pdo_mapping.c pdo_mapping.h \
+	pdo_list.c pdo_list.h \
 	sdo.c sdo.h \
 	sdo_entry.c sdo_entry.h \
 	sdo_request.c sdo_request.h \
--- a/master/fmmu_config.c	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/fmmu_config.c	Thu Apr 03 13:34:13 2008 +0000
@@ -62,7 +62,7 @@
     fmmu->dir = dir;
 
     fmmu->logical_start_address = domain->data_size;
-    fmmu->data_size = ec_pdo_mapping_total_size(&sc->mapping[dir]);
+    fmmu->data_size = ec_pdo_list_total_size(&sc->pdos[dir]);
 
     ec_domain_add_fmmu_config(domain, fmmu);
 }
--- a/master/fsm_coe_map.c	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/fsm_coe_map.c	Thu Apr 03 13:34:13 2008 +0000
@@ -33,7 +33,7 @@
 
 /**
    \file
-   EtherCAT CoE mapping state machines.
+   EtherCAT Pdo information state machines.
 */
 
 /*****************************************************************************/
@@ -73,7 +73,7 @@
     fsm->fsm_coe = fsm_coe;
     fsm->state = NULL;
     ec_sdo_request_init(&fsm->request);
-    ec_pdo_mapping_init(&fsm->mapping);
+    ec_pdo_list_init(&fsm->pdos);
 }
 
 /*****************************************************************************/
@@ -85,7 +85,7 @@
 void ec_fsm_coe_map_clear(ec_fsm_coe_map_t *fsm /**< finite state machine */)
 {
     ec_sdo_request_clear(&fsm->request);
-    ec_pdo_mapping_clear(&fsm->mapping);
+    ec_pdo_list_clear(&fsm->pdos);
 }
 
 /*****************************************************************************/
@@ -135,14 +135,14 @@
  *****************************************************************************/
 
 /**
- * Start reading mapping.
+ * Start reading Pdo assignment.
  */
 
 void ec_fsm_coe_map_state_start(
         ec_fsm_coe_map_t *fsm /**< finite state machine */
         )
 {
-    // read mapping for first direction
+    // 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);
 }
@@ -150,7 +150,7 @@
 /*****************************************************************************/
 
 /**
- * Read mapping of next direction manager.
+ * Read Pdo assignment of next direction manager.
  */
 
 void ec_fsm_coe_map_action_next_dir(
@@ -176,10 +176,10 @@
         fsm->sync_sdo_index = 0x1C10 + fsm->sync->index;
 
         if (slave->master->debug_level)
-            EC_DBG("Reading Pdo mapping of sync manager %u of slave %u.\n",
+            EC_DBG("Reading Pdo assignment of sync manager %u of slave %u.\n",
                     fsm->sync->index, slave->ring_position);
 
-        ec_pdo_mapping_clear_pdos(&fsm->mapping);
+        ec_pdo_list_clear_pdos(&fsm->pdos);
 
         ec_sdo_request_address(&fsm->request, fsm->sync_sdo_index, 0);
         ecrt_sdo_request_read(&fsm->request);
@@ -190,7 +190,7 @@
     }
 
     if (slave->master->debug_level)
-        EC_DBG("Reading of Pdo mapping finished for slave %u.\n",
+        EC_DBG("Reading of Pdo assignment finished for slave %u.\n",
                 slave->ring_position);
 
     fsm->state = ec_fsm_coe_map_state_end;
@@ -199,7 +199,7 @@
 /*****************************************************************************/
 
 /**
- * Count mapped Pdos.
+ * Count assigned Pdos.
  */
 
 void ec_fsm_coe_map_state_pdo_count(
@@ -218,7 +218,7 @@
     fsm->sync_subindices = EC_READ_U8(fsm->request.data);
 
     if (fsm->slave->master->debug_level)
-        EC_DBG("  %u Pdos mapped.\n", fsm->sync_subindices);
+        EC_DBG("  %u Pdos assigned.\n", fsm->sync_subindices);
 
     // read first Pdo
     fsm->sync_subindex = 1;
@@ -245,15 +245,15 @@
         return;
     }
 
-    // finished reading Pdo mapping/configuration
+    // finished reading Pdo assignment/mapping
     
-    if (ec_pdo_mapping_copy(&fsm->sync->mapping, &fsm->mapping)) {
-        fsm->state = ec_fsm_coe_map_state_error;
-        return;
-    }
-
-    fsm->sync->mapping_source = EC_SYNC_MAPPING_COE;
-    ec_pdo_mapping_clear_pdos(&fsm->mapping);
+    if (ec_pdo_list_copy(&fsm->sync->pdos, &fsm->pdos)) {
+        fsm->state = ec_fsm_coe_map_state_error;
+        return;
+    }
+
+    fsm->sync->assign_source = EC_ASSIGN_COE;
+    ec_pdo_list_clear_pdos(&fsm->pdos);
 
     // next direction
     ec_fsm_coe_map_action_next_dir(fsm);
@@ -272,7 +272,7 @@
     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
 
     if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        EC_ERR("Failed to read mapped Pdo index from slave %u.\n",
+        EC_ERR("Failed to read assigned Pdo index from slave %u.\n",
                 fsm->slave->ring_position);
         fsm->state = ec_fsm_coe_map_state_error;
         return;
@@ -292,7 +292,7 @@
     if (fsm->slave->master->debug_level)
         EC_DBG("  Pdo 0x%04X.\n", fsm->pdo->index);
 
-    list_add_tail(&fsm->pdo->list, &fsm->mapping.pdos);
+    list_add_tail(&fsm->pdo->list, &fsm->pdos.list);
 
     ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0);
     ecrt_sdo_request_read(&fsm->request);
@@ -304,7 +304,7 @@
 /*****************************************************************************/
 
 /**
- * Read number of Pdo entries.
+ * Read number of mapped Pdo entries.
  */
 
 void ec_fsm_coe_map_state_pdo_entry_count(
@@ -367,7 +367,7 @@
     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
 
     if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        EC_ERR("Failed to read index of mapped Pdo entry from slave %u.\n",
+        EC_ERR("Failed to read mapped Pdo entry from slave %u.\n",
                 fsm->slave->ring_position);
         fsm->state = ec_fsm_coe_map_state_error;
         return;
--- a/master/fsm_coe_map.h	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/fsm_coe_map.h	Thu Apr 03 13:34:13 2008 +0000
@@ -67,11 +67,11 @@
     uint8_t sync_subindices; /**< number of mapped Pdos */
     uint16_t sync_subindex; /**< current subindex in mapping Sdo */
 
-    ec_pdo_mapping_t mapping; /**< Mapping to apply. */
-    ec_pdo_t *pdo; /**< current Pdo */
-    ec_sdo_t *pdo_sdo; /**< current Pdo Sdo */
-    uint8_t pdo_subindices; /**< number of Pdo entries */
-    uint16_t pdo_subindex; /**< current subindex in Pdo Sdo */
+    ec_pdo_list_t pdos; /**< List of read in Pdos. */
+    ec_pdo_t *pdo; /**< Current Pdo. */
+    ec_sdo_t *pdo_sdo; /**< Current Pdo Sdo. */
+    uint8_t pdo_subindices; /**< Number of Pdo entries. */
+    uint16_t pdo_subindex; /**< Current subindex in Pdo Sdo. */
 };
 
 /*****************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/fsm_pdo_assign.c	Thu Apr 03 13:34:13 2008 +0000
@@ -0,0 +1,380 @@
+/******************************************************************************
+ *
+ *  $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 Pdo assignment state machine.
+ */
+
+/*****************************************************************************/
+
+#include "globals.h"
+#include "master.h"
+#include "mailbox.h"
+#include "slave_config.h"
+
+#include "fsm_pdo_assign.h"
+
+/*****************************************************************************/
+
+void ec_fsm_pdo_assign_state_start(ec_fsm_pdo_assign_t *);
+void ec_fsm_pdo_assign_state_zero_count(ec_fsm_pdo_assign_t *);
+void ec_fsm_pdo_assign_state_add_pdo(ec_fsm_pdo_assign_t *);
+void ec_fsm_pdo_assign_state_pdo_count(ec_fsm_pdo_assign_t *);
+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 *);
+
+/*****************************************************************************/
+
+/** Constructor.
+ */
+void ec_fsm_pdo_assign_init(
+        ec_fsm_pdo_assign_t *fsm, /**< Pdo assignment state machine. */
+        ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */
+        )
+{
+    fsm->fsm_coe = fsm_coe;
+    ec_sdo_request_init(&fsm->request);
+}
+
+/*****************************************************************************/
+
+/** Destructor.
+ */
+void ec_fsm_pdo_assign_clear(
+        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+    ec_sdo_request_clear(&fsm->request);
+}
+
+/*****************************************************************************/
+
+/** Start Pdo assignment state machine.
+ */
+void ec_fsm_pdo_assign_start(
+        ec_fsm_pdo_assign_t *fsm, /**< Pdo assignment state machine. */
+        ec_slave_t *slave /**< slave to configure */
+        )
+{
+    fsm->slave = slave;
+    fsm->state = ec_fsm_pdo_assign_state_start;
+}
+
+/*****************************************************************************/
+
+/** Get running state.
+ *
+ * \return false, if state machine has terminated
+ */
+int ec_fsm_pdo_assign_running(
+        const ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+    return fsm->state != ec_fsm_pdo_assign_state_end
+        && fsm->state != ec_fsm_pdo_assign_state_error;
+}
+
+/*****************************************************************************/
+
+/** Executes the current state of the state machine.
+ *
+ * If the state machine's datagram is not sent or received yet, the execution
+ * of the state machine is delayed to the next cycle.
+ *
+ * \return false, if state machine has terminated
+ */
+int ec_fsm_pdo_assign_exec(
+        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+    fsm->state(fsm);
+    return ec_fsm_pdo_assign_running(fsm);
+}
+
+/*****************************************************************************/
+
+/** Get execution result.
+ *
+ * \return true, if the state machine terminated gracefully
+ */
+int ec_fsm_pdo_assign_success(
+        const ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+    return fsm->state == ec_fsm_pdo_assign_state_end;
+}
+
+/******************************************************************************
+ * State functions.
+ *****************************************************************************/
+
+/** Start Pdo assignment.
+ */
+void ec_fsm_pdo_assign_state_start(
+        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+    if (!fsm->slave->config) {
+        fsm->state = ec_fsm_pdo_assign_state_end;
+        return;
+    }
+
+    fsm->dir = (ec_direction_t) -1; // next is EC_DIR_OUTPUT
+    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];
+        
+        if (!(fsm->sync = ec_slave_get_pdo_sync(fsm->slave, fsm->dir))) {
+            if (!list_empty(&fsm->pdos->list)) {
+                EC_ERR("No sync manager for direction %u!\n", fsm->dir);
+                fsm->state = ec_fsm_pdo_assign_state_end;
+                return;
+            }
+            continue;
+        }
+
+        // check if assignment has to be altered
+        if (ec_pdo_list_equal(&fsm->sync->pdos, fsm->pdos))
+            continue;
+
+        // 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
+                    && !fsm->slave->sii.coe_details.enable_pdo_assign)) {
+            EC_ERR("Slave %u does not support assigning Pdos!\n",
+                    fsm->slave->ring_position);
+            fsm->state = ec_fsm_pdo_assign_state_error;
+            return;
+        }
+
+        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);
+        }
+
+        if (ec_sdo_request_alloc(&fsm->request, 2)) {
+            fsm->state = ec_fsm_pdo_assign_state_error;
+            return;
+        }
+
+        // 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);
+        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);
+
+        fsm->state = ec_fsm_pdo_assign_state_zero_count;
+        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
+        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
+        return;
+    }
+
+    if (fsm->slave->master->debug_level)
+        EC_DBG("Pdo assignment finished for slave %u.\n",
+                fsm->slave->ring_position);
+    fsm->state = ec_fsm_pdo_assign_state_end;
+}
+
+/*****************************************************************************/
+
+/** Assign next Pdo.
+ */
+ec_pdo_t *ec_fsm_pdo_assign_next_pdo(
+        const ec_fsm_pdo_assign_t *fsm, /**< Pdo assignment state machine. */
+        const struct list_head *list /**< current Pdo list item */
+        )
+{
+    list = list->next; 
+    if (list == &fsm->pdos->list)
+        return NULL; // no next Pdo
+    return list_entry(list, ec_pdo_t, list);
+}
+
+/*****************************************************************************/
+
+/** Assign a Pdo.
+ */
+void ec_fsm_pdo_assign_add_pdo(
+        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+    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);
+    ecrt_sdo_request_write(&fsm->request);
+    if (fsm->slave->master->debug_level)
+        EC_DBG("Assigning Pdo 0x%04X at position %u.\n",
+                fsm->pdo->index, fsm->pdo_count);
+    
+    fsm->state = ec_fsm_pdo_assign_state_add_pdo;
+    ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
+    ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
+}
+
+/*****************************************************************************/
+
+/** Set the number of assigned Pdos to zero.
+ */
+void ec_fsm_pdo_assign_state_zero_count(
+        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_ERR("Failed to clear Pdo assignment of slave %u.\n",
+                fsm->slave->ring_position);
+        fsm->state = ec_fsm_pdo_assign_state_error;
+        return;
+    }
+
+    // assign all Pdos belonging to the current sync manager
+    
+    // find first Pdo
+    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);
+        return;
+    }
+
+    // assign first Pdo
+    fsm->pdo_count = 1;
+    ec_fsm_pdo_assign_add_pdo(fsm);
+}
+
+/*****************************************************************************/
+
+/** Add a Pdo to the sync managers Pdo assignment.
+ */
+void ec_fsm_pdo_assign_state_add_pdo(
+        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
+
+    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->state = ec_fsm_pdo_assign_state_error;
+        return;
+    }
+
+    // find next Pdo
+    if (!(fsm->pdo = ec_fsm_pdo_assign_next_pdo(fsm, &fsm->pdo->list))) {
+        // 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);
+        ecrt_sdo_request_write(&fsm->request);
+        if (fsm->slave->master->debug_level)
+            EC_DBG("Setting number of assigned Pdos to %u.\n",
+                    fsm->pdo_count);
+        
+        fsm->state = ec_fsm_pdo_assign_state_pdo_count;
+        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
+        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
+        return;
+    }
+
+    // add next Pdo to assignment
+    fsm->pdo_count++;
+    ec_fsm_pdo_assign_add_pdo(fsm);
+}
+
+/*****************************************************************************/
+
+/** Set the number of assigned Pdos.
+ */
+void ec_fsm_pdo_assign_state_pdo_count(
+        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_ERR("Failed to set number of assigned Pdos for slave %u.\n",
+                fsm->slave->ring_position);
+        fsm->state = ec_fsm_pdo_assign_state_error;
+        return;
+    }
+
+    if (fsm->slave->master->debug_level)
+        EC_DBG("Successfully set 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);
+}
+
+/******************************************************************************
+ * Common state functions
+ *****************************************************************************/
+
+/** State: ERROR.
+ */
+void ec_fsm_pdo_assign_state_error(
+        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+}
+
+/*****************************************************************************/
+
+/** State: END.
+ */
+void ec_fsm_pdo_assign_state_end(
+        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
+        )
+{
+}
+
+/*****************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/fsm_pdo_assign.h	Thu Apr 03 13:34:13 2008 +0000
@@ -0,0 +1,85 @@
+/******************************************************************************
+ *
+ *  $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 Pdo assignment state machine structures.
+*/
+
+/*****************************************************************************/
+
+#ifndef _EC_FSM_PDO_ASSIGN_H_
+#define _EC_FSM_PDO_ASSIGN_H_
+
+#include "../include/ecrt.h"
+
+#include "globals.h"
+#include "datagram.h"
+#include "fsm_coe.h"
+
+/*****************************************************************************/
+
+/**
+ * \see ec_fsm_pdo_assign
+ */
+typedef struct ec_fsm_pdo_assign ec_fsm_pdo_assign_t;
+
+/** Pdo assignment state machine.
+ */
+struct ec_fsm_pdo_assign
+{
+    void (*state)(ec_fsm_pdo_assign_t *); /**< State function. */
+    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. */
+    const ec_sync_t *sync; /**< Current sync manager. */
+    const ec_pdo_list_t *pdos; /**< Target Pdo assignment. */
+    const ec_pdo_t *pdo; /**< Current Pdo. */
+
+    ec_sdo_request_t request; /**< Sdo request. */
+    unsigned int pdo_count; /**< Number of assigned Pdos. */
+};
+
+/*****************************************************************************/
+
+void ec_fsm_pdo_assign_init(ec_fsm_pdo_assign_t *, ec_fsm_coe_t *);
+void ec_fsm_pdo_assign_clear(ec_fsm_pdo_assign_t *);
+
+void ec_fsm_pdo_assign_start(ec_fsm_pdo_assign_t *, ec_slave_t *);
+int ec_fsm_pdo_assign_exec(ec_fsm_pdo_assign_t *);
+int ec_fsm_pdo_assign_success(const ec_fsm_pdo_assign_t *);
+
+/*****************************************************************************/
+
+#endif
--- a/master/fsm_pdo_config.c	Mon Mar 31 09:42:37 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,385 +0,0 @@
-/******************************************************************************
- *
- *  $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 Pdo configuration state machine.
- */
-
-/*****************************************************************************/
-
-#include "globals.h"
-#include "master.h"
-#include "mailbox.h"
-#include "slave_config.h"
-
-#include "fsm_pdo_config.h"
-
-/*****************************************************************************/
-
-void ec_fsm_pdo_config_state_start(ec_fsm_pdo_config_t *);
-void ec_fsm_pdo_config_state_zero_count(ec_fsm_pdo_config_t *);
-void ec_fsm_pdo_config_state_add_entry(ec_fsm_pdo_config_t *);
-void ec_fsm_pdo_config_state_entry_count(ec_fsm_pdo_config_t *);
-void ec_fsm_pdo_config_state_end(ec_fsm_pdo_config_t *);
-void ec_fsm_pdo_config_state_error(ec_fsm_pdo_config_t *);
-
-void ec_fsm_pdo_config_next_pdo(ec_fsm_pdo_config_t *);
-
-/*****************************************************************************/
-
-/** Constructor.
- */
-void ec_fsm_pdo_config_init(
-        ec_fsm_pdo_config_t *fsm, /**< pdo_config state machine */
-        ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */
-        )
-{
-    fsm->fsm_coe = fsm_coe;
-    ec_sdo_request_init(&fsm->request);
-}
-
-/*****************************************************************************/
-
-/** Destructor.
- */
-void ec_fsm_pdo_config_clear(
-        ec_fsm_pdo_config_t *fsm /**< pdo_config state machine */
-        )
-{
-    ec_sdo_request_clear(&fsm->request);
-}
-
-/*****************************************************************************/
-
-/** Start Pdo configuration state machine.
- */
-void ec_fsm_pdo_config_start(
-        ec_fsm_pdo_config_t *fsm, /**< Pdo configuration state machine */
-        ec_slave_t *slave /**< slave to configure */
-        )
-{
-    fsm->slave = slave;
-    fsm->state = ec_fsm_pdo_config_state_start;
-}
-
-/*****************************************************************************/
-
-/** Get running state.
- *
- * \return false, if state machine has terminated
- */
-int ec_fsm_pdo_config_running(
-        const ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine */
-        )
-{
-    return fsm->state != ec_fsm_pdo_config_state_end
-        && fsm->state != ec_fsm_pdo_config_state_error;
-}
-
-/*****************************************************************************/
-
-/** Executes the current state.
- *
- * \return false, if state machine has terminated
- */
-int ec_fsm_pdo_config_exec(
-        ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine */
-        )
-{
-    fsm->state(fsm);
-    return ec_fsm_pdo_config_running(fsm);
-}
-
-/*****************************************************************************/
-
-/** Get execution result.
- *
- * \return true, if the state machine terminated gracefully
- */
-int ec_fsm_pdo_config_success(
-        const ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine */
-        )
-{
-    return fsm->state == ec_fsm_pdo_config_state_end;
-}
-
-/******************************************************************************
- * State functions.
- *****************************************************************************/
-
-/** Start Pdo configuration.
- */
-void ec_fsm_pdo_config_state_start(
-        ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine */
-        )
-{
-    if (!fsm->slave->config) {
-        fsm->state = ec_fsm_pdo_config_state_end;
-        return;
-    }
-
-    fsm->pdo = NULL;
-    ec_fsm_pdo_config_next_pdo(fsm);
-}
-
-/*****************************************************************************/
-
-/** Process configuration of next Pdo.
- */
-void ec_fsm_pdo_config_next_pdo(
-        ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine */
-        )
-{
-    ec_direction_t dir;
-    const ec_pdo_mapping_t *map;
-    const ec_pdo_t *pdo, *mapped_pdo;
-    
-    for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) {
-        map = &fsm->slave->config->mapping[dir];
-
-        list_for_each_entry(pdo, &map->pdos, list) {
-            if (fsm->pdo) { // there was a Pdo configured in the last run
-                if (pdo == fsm->pdo) // this is the last Pdo
-                    fsm->pdo = NULL; // take the next one
-            } else {
-                if ((mapped_pdo = ec_slave_find_pdo(fsm->slave, pdo->index)))
-                    if (ec_pdo_equal_entries(pdo, mapped_pdo))
-                        continue; // Pdo configured correctly
-
-                fsm->pdo = pdo;
-                break;
-            }
-        }
-    }
-
-    if (!fsm->pdo) {
-        if (fsm->slave->master->debug_level)
-            EC_DBG("Pdo configuration finished for slave %u.\n",
-                    fsm->slave->ring_position);
-        fsm->state = ec_fsm_pdo_config_state_end;
-        return;
-    }
-
-    // Pdo configuration has to be changed. Does the slave support this?
-    if (!(fsm->slave->sii.mailbox_protocols & EC_MBOX_COE)
-            || (fsm->slave->sii.has_general
-                && !fsm->slave->sii.coe_details.enable_pdo_configuration)) {
-        EC_ERR("Slave %u does not support changing the Pdo configuration!\n",
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_pdo_config_state_error;
-        return;
-    }
-
-    if (fsm->slave->master->debug_level) {
-        EC_DBG("Changing configuration of Pdo 0x%04X of slave %u.\n",
-                fsm->pdo->index, fsm->slave->ring_position);
-    }
-
-    if (ec_sdo_request_alloc(&fsm->request, 4)) {
-        fsm->state = ec_fsm_pdo_config_state_error;
-        return;
-    }
-
-    // set mapped Pdo count to zero
-    EC_WRITE_U8(fsm->request.data, 0);
-    fsm->request.data_size = 1;
-    ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0);
-    ecrt_sdo_request_write(&fsm->request);
-    if (fsm->slave->master->debug_level)
-        EC_DBG("Setting entry count to zero for Pdo 0x%04X.\n",
-                fsm->pdo->index);
-
-    fsm->state = ec_fsm_pdo_config_state_zero_count;
-    ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
-    ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
-}
-
-/*****************************************************************************/
-
-/** Process next Pdo entry.
- */
-ec_pdo_entry_t *ec_fsm_pdo_config_next_entry(
-        const ec_fsm_pdo_config_t *fsm, /**< Pdo configuration state machine */
-        const struct list_head *list /**< current entry list item */
-        )
-{
-    list = list->next; 
-    if (list == &fsm->pdo->entries)
-        return NULL; // no next entry
-    return list_entry(list, ec_pdo_entry_t, list);
-}
-
-/*****************************************************************************/
-
-/** Starts to add a Pdo entry.
- */
-void ec_fsm_pdo_config_add_entry(
-        ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine. */
-        )
-{
-    uint32_t value;
-
-    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_config_state_add_entry;
-    ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
-    ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
-}
-
-/*****************************************************************************/
-
-/** Set the number of configured entries to zero.
- */
-void ec_fsm_pdo_config_state_zero_count(
-        ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine */
-        )
-{
-    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
-
-    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        EC_ERR("Failed to clear Pdo configuration for slave %u.\n",
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_pdo_config_state_error;
-        return;
-    }
-
-    // find first entry
-    if (!(fsm->entry =
-                ec_fsm_pdo_config_next_entry(fsm, &fsm->pdo->entries))) {
-        if (fsm->slave->master->debug_level)
-            EC_DBG("No entries to configure for Pdo 0x%04X of slave %u.\n",
-                    fsm->pdo->index, fsm->slave->ring_position);
-        ec_fsm_pdo_config_next_pdo(fsm);
-        return;
-    }
-
-    // add first entry
-    fsm->entry_count = 1;
-    ec_fsm_pdo_config_add_entry(fsm);
-}
-
-/*****************************************************************************/
-
-/** Add a Pdo entry.
- */
-void ec_fsm_pdo_config_state_add_entry(
-        ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine */
-        )
-{
-    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
-
-    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        EC_ERR("Failed to add entry 0x%04X:%u for slave %u.\n",
-                fsm->entry->index, fsm->entry->subindex,
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_pdo_config_state_error;
-        return;
-    }
-
-    // find next entry
-    if (!(fsm->entry = ec_fsm_pdo_config_next_entry(fsm, &fsm->entry->list))) {
-        // No more entries to add. Write entry count.
-        EC_WRITE_U8(fsm->request.data, fsm->entry_count);
-        fsm->request.data_size = 1;
-        ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0);
-        ecrt_sdo_request_write(&fsm->request);
-        if (fsm->slave->master->debug_level)
-            EC_DBG("Setting number of Pdo entries to %u.\n",
-                    fsm->entry_count);
-        
-        fsm->state = ec_fsm_pdo_config_state_entry_count;
-        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
-        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
-        return;
-    }
-
-    // add next entry
-    fsm->entry_count++;
-    ec_fsm_pdo_config_add_entry(fsm);
-}
-
-/*****************************************************************************/
-
-/** Set the number of entries.
- */
-void ec_fsm_pdo_config_state_entry_count(
-        ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine */
-        )
-{
-    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
-
-    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        EC_ERR("Failed to set number of entries for slave %u.\n",
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_pdo_config_state_error;
-        return;
-    }
-
-    if (fsm->slave->master->debug_level)
-        EC_DBG("Successfully configured Pdo 0x%04X on slave %u.\n",
-                fsm->pdo->index, fsm->slave->ring_position);
-
-    ec_fsm_pdo_config_next_pdo(fsm);
-}
-
-/******************************************************************************
- * Common state functions
- *****************************************************************************/
-
-/** State: ERROR.
- */
-void ec_fsm_pdo_config_state_error(
-        ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine */
-        )
-{
-}
-
-/*****************************************************************************/
-
-/** State: END.
- */
-void ec_fsm_pdo_config_state_end(
-        ec_fsm_pdo_config_t *fsm /**< Pdo configuration state machine */
-        )
-{
-}
-
-/*****************************************************************************/
--- a/master/fsm_pdo_config.h	Mon Mar 31 09:42:37 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/******************************************************************************
- *
- *  $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 Pdo configuration state machine structures.
- */
-
-/*****************************************************************************/
-
-#ifndef __EC_FSM_PDO_CONFIG__
-#define __EC_FSM_PDO_CONFIG__
-
-#include "globals.h"
-#include "../include/ecrt.h"
-#include "datagram.h"
-#include "fsm_coe.h"
-
-/*****************************************************************************/
-
-/**
- * \see ec_fsm_pdo_config
- */
-typedef struct ec_fsm_pdo_config ec_fsm_pdo_config_t;
-
-/** Pdo configuration state machine.
- */
-struct ec_fsm_pdo_config
-{
-    void (*state)(ec_fsm_pdo_config_t *); /**< state function */
-    ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use */
-    ec_slave_t *slave; /**< Slave the FSM runs on. */
-
-    const ec_pdo_t *pdo; /**< Current Pdo to configure. */
-    const ec_pdo_entry_t *entry; /**< Current entry. */
-
-    ec_sdo_request_t request; /**< Sdo request. */
-    unsigned int entry_count; /**< Number of configured entries. */
-};
-
-/*****************************************************************************/
-
-void ec_fsm_pdo_config_init(ec_fsm_pdo_config_t *, ec_fsm_coe_t *);
-void ec_fsm_pdo_config_clear(ec_fsm_pdo_config_t *);
-
-void ec_fsm_pdo_config_start(ec_fsm_pdo_config_t *, ec_slave_t *);
-int ec_fsm_pdo_config_exec(ec_fsm_pdo_config_t *);
-int ec_fsm_pdo_config_success(const ec_fsm_pdo_config_t *);
-
-/*****************************************************************************/
-
-#endif
--- a/master/fsm_pdo_mapping.c	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/fsm_pdo_mapping.c	Thu Apr 03 13:34:13 2008 +0000
@@ -48,20 +48,20 @@
 
 void ec_fsm_pdo_mapping_state_start(ec_fsm_pdo_mapping_t *);
 void ec_fsm_pdo_mapping_state_zero_count(ec_fsm_pdo_mapping_t *);
-void ec_fsm_pdo_mapping_state_add_pdo(ec_fsm_pdo_mapping_t *);
-void ec_fsm_pdo_mapping_state_pdo_count(ec_fsm_pdo_mapping_t *);
+void ec_fsm_pdo_mapping_state_add_entry(ec_fsm_pdo_mapping_t *);
+void ec_fsm_pdo_mapping_state_entry_count(ec_fsm_pdo_mapping_t *);
 void ec_fsm_pdo_mapping_state_end(ec_fsm_pdo_mapping_t *);
 void ec_fsm_pdo_mapping_state_error(ec_fsm_pdo_mapping_t *);
 
-void ec_fsm_pdo_mapping_next_dir(ec_fsm_pdo_mapping_t *);
+void ec_fsm_pdo_mapping_next_pdo(ec_fsm_pdo_mapping_t *);
 
 /*****************************************************************************/
 
 /** Constructor.
  */
 void ec_fsm_pdo_mapping_init(
-        ec_fsm_pdo_mapping_t *fsm, /**< mapping state machine */
-        ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */
+        ec_fsm_pdo_mapping_t *fsm, /**< Pdo mapping state machine. */
+        ec_fsm_coe_t *fsm_coe /**< CoE state machine to use. */
         )
 {
     fsm->fsm_coe = fsm_coe;
@@ -73,7 +73,7 @@
 /** Destructor.
  */
 void ec_fsm_pdo_mapping_clear(
-        ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
+        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
         )
 {
     ec_sdo_request_clear(&fsm->request);
@@ -81,10 +81,10 @@
 
 /*****************************************************************************/
 
-/** Start Pdo mapping configuration state machine.
+/** Start Pdo mapping state machine.
  */
 void ec_fsm_pdo_mapping_start(
-        ec_fsm_pdo_mapping_t *fsm, /**< mapping state machine */
+        ec_fsm_pdo_mapping_t *fsm, /**< Pdo mapping state machine. */
         ec_slave_t *slave /**< slave to configure */
         )
 {
@@ -99,7 +99,7 @@
  * \return false, if state machine has terminated
  */
 int ec_fsm_pdo_mapping_running(
-        const ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
+        const ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
         )
 {
     return fsm->state != ec_fsm_pdo_mapping_state_end
@@ -108,15 +108,12 @@
 
 /*****************************************************************************/
 
-/** Executes the current state of the state machine.
- *
- * If the state machine's datagram is not sent or received yet, the execution
- * of the state machine is delayed to the next cycle.
+/** Executes the current state.
  *
  * \return false, if state machine has terminated
  */
 int ec_fsm_pdo_mapping_exec(
-        ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
+        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
         )
 {
     fsm->state(fsm);
@@ -130,7 +127,7 @@
  * \return true, if the state machine terminated gracefully
  */
 int ec_fsm_pdo_mapping_success(
-        const ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
+        const ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
         )
 {
     return fsm->state == ec_fsm_pdo_mapping_state_end;
@@ -140,10 +137,10 @@
  * State functions.
  *****************************************************************************/
 
-/** Start mapping configuration.
+/** Start Pdo mapping.
  */
 void ec_fsm_pdo_mapping_state_start(
-        ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
+        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
         )
 {
     if (!fsm->slave->config) {
@@ -151,119 +148,128 @@
         return;
     }
 
-    fsm->dir = (ec_direction_t) -1; // next is EC_DIR_OUTPUT
-    ec_fsm_pdo_mapping_next_dir(fsm);
-}
-
-/*****************************************************************************/
-
-/** Process mapping of next direction.
- */
-void ec_fsm_pdo_mapping_next_dir(
-        ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
-        )
-{
-    fsm->dir++;
-
-    for (; fsm->dir <= EC_DIR_INPUT; fsm->dir++) {
-        fsm->mapping = &fsm->slave->config->mapping[fsm->dir];
-        
-        if (!(fsm->sync = ec_slave_get_pdo_sync(fsm->slave, fsm->dir))) {
-            if (!list_empty(&fsm->mapping->pdos)) {
-                EC_ERR("No sync manager for direction %u!\n", fsm->dir);
-                fsm->state = ec_fsm_pdo_mapping_state_end;
-                return;
+    fsm->pdo = NULL;
+    ec_fsm_pdo_mapping_next_pdo(fsm);
+}
+
+/*****************************************************************************/
+
+/** Process mapping of next Pdo.
+ */
+void ec_fsm_pdo_mapping_next_pdo(
+        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    ec_direction_t dir;
+    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];
+
+        list_for_each_entry(pdo, &pdos->list, list) {
+            if (fsm->pdo) { // there was a Pdo mapping changed in the last run
+                if (pdo == fsm->pdo) // this is the last Pdo
+                    fsm->pdo = NULL; // take the next one
+            } else {
+                if ((assigned_pdo = ec_slave_find_pdo(fsm->slave, pdo->index)))
+                    if (ec_pdo_equal_entries(pdo, assigned_pdo))
+                        continue; // Pdo entries mapped correctly
+
+                fsm->pdo = pdo;
+                break;
             }
-            continue;
         }
-
-        // check if mapping has to be altered
-        if (ec_pdo_mapping_equal(&fsm->sync->mapping, fsm->mapping))
-            continue;
-
-        // Pdo mapping has to be changed. Does the slave support this?
-        if (!fsm->slave->sii.mailbox_protocols & EC_MBOX_COE
-                || (fsm->slave->sii.has_general
-                    && !fsm->slave->sii.coe_details.enable_pdo_assign)) {
-            EC_ERR("Slave %u does not support changing the Pdo mapping!\n",
+    }
+
+    if (!fsm->pdo) {
+        if (fsm->slave->master->debug_level)
+            EC_DBG("Pdo mapping finished for slave %u.\n",
                     fsm->slave->ring_position);
-            fsm->state = ec_fsm_pdo_mapping_state_error;
-            return;
-        }
-
-        if (fsm->slave->master->debug_level) {
-            EC_DBG("Changing Pdo mapping for SM%u of slave %u.\n",
-                    fsm->sync->index, fsm->slave->ring_position);
-        }
-
-        if (ec_sdo_request_alloc(&fsm->request, 2)) {
-            fsm->state = ec_fsm_pdo_mapping_state_error;
-            return;
-        }
-
-        // 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);
-        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);
-
-        fsm->state = ec_fsm_pdo_mapping_state_zero_count;
-        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
-        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
-        return;
-    }
-
-    if (fsm->slave->master->debug_level)
-        EC_DBG("Pdo mapping finished for slave %u.\n",
+        fsm->state = ec_fsm_pdo_mapping_state_end;
+        return;
+    }
+
+    // Pdo mapping has to be changed. Does the slave support this?
+    if (!(fsm->slave->sii.mailbox_protocols & EC_MBOX_COE)
+            || (fsm->slave->sii.has_general
+                && !fsm->slave->sii.coe_details.enable_pdo_configuration)) {
+        EC_ERR("Slave %u does not support changing the Pdo mapping!\n",
                 fsm->slave->ring_position);
-    fsm->state = ec_fsm_pdo_mapping_state_end;
-}
-
-/*****************************************************************************/
-
-/** Process mapping of next Pdo.
- */
-ec_pdo_t *ec_fsm_pdo_mapping_next_pdo(
-        const ec_fsm_pdo_mapping_t *fsm, /**< mapping state machine */
-        const struct list_head *list /**< current Pdo list item */
-        )
-{
-    list = list->next; 
-    if (list == &fsm->mapping->pdos)
-        return NULL; // no next Pdo
-    return list_entry(list, ec_pdo_t, list);
-}
-
-/*****************************************************************************/
-
-/** Add a Pdo to the mapping.
- */
-void ec_fsm_pdo_mapping_add_pdo(
-        ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
-        )
-{
-    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);
+        fsm->state = ec_fsm_pdo_mapping_state_error;
+        return;
+    }
+
+    if (fsm->slave->master->debug_level) {
+        EC_DBG("Changing mapping of Pdo 0x%04X of slave %u.\n",
+                fsm->pdo->index, fsm->slave->ring_position);
+    }
+
+    if (ec_sdo_request_alloc(&fsm->request, 4)) {
+        fsm->state = ec_fsm_pdo_mapping_state_error;
+        return;
+    }
+
+    // set mapped Pdo count to zero
+    EC_WRITE_U8(fsm->request.data, 0);
+    fsm->request.data_size = 1;
+    ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0);
     ecrt_sdo_request_write(&fsm->request);
     if (fsm->slave->master->debug_level)
-        EC_DBG("Mapping Pdo 0x%04X at position %u.\n",
-                fsm->pdo->index, fsm->pdo_count);
-    
-    fsm->state = ec_fsm_pdo_mapping_state_add_pdo;
+        EC_DBG("Setting entry count to zero for Pdo 0x%04X.\n",
+                fsm->pdo->index);
+
+    fsm->state = ec_fsm_pdo_mapping_state_zero_count;
     ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
     ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
 }
 
 /*****************************************************************************/
 
-/** Set the number of mapped Pdos to zero.
+/** Process next Pdo entry.
+ */
+ec_pdo_entry_t *ec_fsm_pdo_mapping_next_entry(
+        const ec_fsm_pdo_mapping_t *fsm, /**< Pdo mapping state machine. */
+        const struct list_head *list /**< current entry list item */
+        )
+{
+    list = list->next; 
+    if (list == &fsm->pdo->entries)
+        return NULL; // no next entry
+    return list_entry(list, ec_pdo_entry_t, list);
+}
+
+/*****************************************************************************/
+
+/** Starts to add a Pdo entry.
+ */
+void ec_fsm_pdo_mapping_add_entry(
+        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    uint32_t value;
+
+    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);
+    ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
+}
+
+/*****************************************************************************/
+
+/** Set the number of mapped entries to zero.
  */
 void ec_fsm_pdo_mapping_state_zero_count(
-        ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
+        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
         )
 {
     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
@@ -275,84 +281,83 @@
         return;
     }
 
-    // map all Pdos belonging to the current sync manager
-    
-    // find first Pdo
-    if (!(fsm->pdo = ec_fsm_pdo_mapping_next_pdo(fsm, &fsm->mapping->pdos))) {
+    // find first entry
+    if (!(fsm->entry =
+                ec_fsm_pdo_mapping_next_entry(fsm, &fsm->pdo->entries))) {
         if (fsm->slave->master->debug_level)
-            EC_DBG("No Pdos to map for SM%u of slave %u.\n",
-                    fsm->sync->index, fsm->slave->ring_position);
-        ec_fsm_pdo_mapping_next_dir(fsm);
-        return;
-    }
-
-    // add first Pdo to mapping
-    fsm->pdo_count = 1;
-    ec_fsm_pdo_mapping_add_pdo(fsm);
-}
-
-/*****************************************************************************/
-
-/** Add a Pdo to the sync managers mapping.
- */
-void ec_fsm_pdo_mapping_state_add_pdo(
-        ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
+            EC_DBG("No entries to map for Pdo 0x%04X of slave %u.\n",
+                    fsm->pdo->index, fsm->slave->ring_position);
+        ec_fsm_pdo_mapping_next_pdo(fsm);
+        return;
+    }
+
+    // add first entry
+    fsm->entry_count = 1;
+    ec_fsm_pdo_mapping_add_entry(fsm);
+}
+
+/*****************************************************************************/
+
+/** Add a Pdo entry.
+ */
+void ec_fsm_pdo_mapping_state_add_entry(
+        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
         )
 {
     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
 
     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->state = ec_fsm_pdo_mapping_state_error;
-        return;
-    }
-
-    // find next Pdo
-    if (!(fsm->pdo = ec_fsm_pdo_mapping_next_pdo(fsm, &fsm->pdo->list))) {
-        // no more Pdos to map. write Pdo count
-        EC_WRITE_U8(fsm->request.data, fsm->pdo_count);
+        EC_ERR("Failed to add entry 0x%04X:%u for slave %u.\n",
+                fsm->entry->index, fsm->entry->subindex,
+                fsm->slave->ring_position);
+        fsm->state = ec_fsm_pdo_mapping_state_error;
+        return;
+    }
+
+    // find next entry
+    if (!(fsm->entry = ec_fsm_pdo_mapping_next_entry(fsm, &fsm->entry->list))) {
+        // No more entries to add. Write entry count.
+        EC_WRITE_U8(fsm->request.data, fsm->entry_count);
         fsm->request.data_size = 1;
-        ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync->index, 0);
+        ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0);
         ecrt_sdo_request_write(&fsm->request);
         if (fsm->slave->master->debug_level)
-            EC_DBG("Setting number of mapped Pdos to %u.\n",
-                    fsm->pdo_count);
+            EC_DBG("Setting number of Pdo entries to %u.\n",
+                    fsm->entry_count);
         
-        fsm->state = ec_fsm_pdo_mapping_state_pdo_count;
+        fsm->state = ec_fsm_pdo_mapping_state_entry_count;
         ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
         ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
         return;
     }
 
-    // add next Pdo to mapping
-    fsm->pdo_count++;
-    ec_fsm_pdo_mapping_add_pdo(fsm);
-}
-
-/*****************************************************************************/
-
-/** Set the number of mapped Pdos.
- */
-void ec_fsm_pdo_mapping_state_pdo_count(
-        ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
+    // add next entry
+    fsm->entry_count++;
+    ec_fsm_pdo_mapping_add_entry(fsm);
+}
+
+/*****************************************************************************/
+
+/** Set the number of entries.
+ */
+void ec_fsm_pdo_mapping_state_entry_count(
+        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
         )
 {
     if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
 
     if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        EC_ERR("Failed to set number of mapped Pdos for slave %u.\n",
+        EC_ERR("Failed to set number of entries for slave %u.\n",
                 fsm->slave->ring_position);
         fsm->state = ec_fsm_pdo_mapping_state_error;
         return;
     }
 
     if (fsm->slave->master->debug_level)
-        EC_DBG("Successfully set Pdo mapping for SM%u of slave %u.\n",
-                fsm->sync->index, fsm->slave->ring_position);
-
-    // mapping configuration for this direction finished
-    ec_fsm_pdo_mapping_next_dir(fsm);
+        EC_DBG("Successfully configured mapping for Pdo 0x%04X on slave %u.\n",
+                fsm->pdo->index, fsm->slave->ring_position);
+
+    ec_fsm_pdo_mapping_next_pdo(fsm);
 }
 
 /******************************************************************************
@@ -362,7 +367,7 @@
 /** State: ERROR.
  */
 void ec_fsm_pdo_mapping_state_error(
-        ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
+        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
         )
 {
 }
@@ -372,9 +377,9 @@
 /** State: END.
  */
 void ec_fsm_pdo_mapping_state_end(
-        ec_fsm_pdo_mapping_t *fsm /**< mapping state machine */
-        )
-{
-}
-
-/*****************************************************************************/
+        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+}
+
+/*****************************************************************************/
--- a/master/fsm_pdo_mapping.h	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/fsm_pdo_mapping.h	Thu Apr 03 13:34:13 2008 +0000
@@ -31,19 +31,17 @@
  *
  *****************************************************************************/
 
-/**
-   \file
-   EtherCAT Pdo mapping state machine structures.
-*/
+/** \file
+ * EtherCAT Pdo configuration state machine structures.
+ */
 
 /*****************************************************************************/
 
 #ifndef __EC_FSM_PDO_MAPPING__
 #define __EC_FSM_PDO_MAPPING__
 
+#include "globals.h"
 #include "../include/ecrt.h"
-
-#include "globals.h"
 #include "datagram.h"
 #include "fsm_coe.h"
 
@@ -54,21 +52,19 @@
  */
 typedef struct ec_fsm_pdo_mapping ec_fsm_pdo_mapping_t;
 
-/** Pdo mapping state machine.
+/** Pdo configuration state machine.
  */
 struct ec_fsm_pdo_mapping
 {
-    void (*state)(ec_fsm_pdo_mapping_t *); /**< State function. */
-    ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use. */
+    void (*state)(ec_fsm_pdo_mapping_t *); /**< state function */
+    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. */
-    const ec_sync_t *sync; /**< Current sync manager. */
-    const ec_pdo_mapping_t *mapping; /**< Target Pdo mapping. */
-    const ec_pdo_t *pdo; /**< Current Pdo. */
+    const ec_pdo_t *pdo; /**< Current Pdo to configure. */
+    const ec_pdo_entry_t *entry; /**< Current entry. */
 
     ec_sdo_request_t request; /**< Sdo request. */
-    unsigned int pdo_count; /**< Number of mapped Pdos. */
+    unsigned int entry_count; /**< Number of configured entries. */
 };
 
 /*****************************************************************************/
--- a/master/fsm_slave_config.c	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/fsm_slave_config.c	Thu Apr 03 13:34:13 2008 +0000
@@ -52,8 +52,8 @@
 void ec_fsm_slave_config_state_mbox_sync(ec_fsm_slave_config_t *);
 void ec_fsm_slave_config_state_preop(ec_fsm_slave_config_t *);
 void ec_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *);
-void ec_fsm_slave_config_state_mapping(ec_fsm_slave_config_t *);
-void ec_fsm_slave_config_state_pdo_conf(ec_fsm_slave_config_t *);
+void ec_fsm_slave_config_state_pdo_assign(ec_fsm_slave_config_t *);
+void ec_fsm_slave_config_state_pdo_mapping(ec_fsm_slave_config_t *);
 void ec_fsm_slave_config_state_pdo_sync(ec_fsm_slave_config_t *);
 void ec_fsm_slave_config_state_fmmu(ec_fsm_slave_config_t *);
 void ec_fsm_slave_config_state_safeop(ec_fsm_slave_config_t *);
@@ -62,7 +62,7 @@
 void ec_fsm_slave_config_enter_mbox_sync(ec_fsm_slave_config_t *);
 void ec_fsm_slave_config_enter_preop(ec_fsm_slave_config_t *);
 void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *);
-void ec_fsm_slave_config_enter_mapping(ec_fsm_slave_config_t *);
+void ec_fsm_slave_config_enter_pdo_assign(ec_fsm_slave_config_t *);
 void ec_fsm_slave_config_enter_pdo_sync(ec_fsm_slave_config_t *);
 void ec_fsm_slave_config_enter_fmmu(ec_fsm_slave_config_t *);
 void ec_fsm_slave_config_enter_safeop(ec_fsm_slave_config_t *);
@@ -83,8 +83,8 @@
     // init sub state machines
     ec_fsm_change_init(&fsm->fsm_change, fsm->datagram);
     ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram);
-    ec_fsm_pdo_mapping_init(&fsm->fsm_pdo_map, &fsm->fsm_coe);
-    ec_fsm_pdo_config_init(&fsm->fsm_pdo_conf, &fsm->fsm_coe);
+    ec_fsm_pdo_assign_init(&fsm->fsm_pdo_assign, &fsm->fsm_coe);
+    ec_fsm_pdo_mapping_init(&fsm->fsm_pdo_mapping, &fsm->fsm_coe);
 }
 
 /*****************************************************************************/
@@ -96,8 +96,8 @@
     // clear sub state machines
     ec_fsm_change_clear(&fsm->fsm_change);
     ec_fsm_coe_clear(&fsm->fsm_coe);
-    ec_fsm_pdo_mapping_clear(&fsm->fsm_pdo_map);
-    ec_fsm_pdo_config_clear(&fsm->fsm_pdo_conf);
+    ec_fsm_pdo_assign_clear(&fsm->fsm_pdo_assign);
+    ec_fsm_pdo_mapping_clear(&fsm->fsm_pdo_mapping);
 }
 
 /*****************************************************************************/
@@ -442,7 +442,7 @@
 
     // No CoE configuration to be applied?
     if (list_empty(&slave->config->sdo_configs)) { // skip Sdo configuration
-        ec_fsm_slave_config_enter_mapping(fsm);
+        ec_fsm_slave_config_enter_pdo_assign(fsm);
         return;
     }
 
@@ -486,65 +486,65 @@
     }
 
     // All Sdos are now configured.
-    ec_fsm_slave_config_enter_mapping(fsm);
-}
-
-/*****************************************************************************/
-
-/**
- * Check for Pdo mappings to be applied.
- */
-
-void ec_fsm_slave_config_enter_mapping(
+    ec_fsm_slave_config_enter_pdo_assign(fsm);
+}
+
+/*****************************************************************************/
+
+/**
+ * Check for alternate Pdo assignments to be applied.
+ */
+
+void ec_fsm_slave_config_enter_pdo_assign(
         ec_fsm_slave_config_t *fsm /**< slave state machine */
         )
 {
-    // start configuring Pdo mapping
-    fsm->state = ec_fsm_slave_config_state_mapping;
-    ec_fsm_pdo_mapping_start(&fsm->fsm_pdo_map, fsm->slave);
-    ec_fsm_pdo_mapping_exec(&fsm->fsm_pdo_map); // execute immediately
-}
-
-/*****************************************************************************/
-
-/**
-   Slave configuration state: MAPPING.
-*/
-
-void ec_fsm_slave_config_state_mapping(
+    // start applying alternate Pdo assignments
+    fsm->state = ec_fsm_slave_config_state_pdo_assign;
+    ec_fsm_pdo_assign_start(&fsm->fsm_pdo_assign, fsm->slave);
+    ec_fsm_pdo_assign_exec(&fsm->fsm_pdo_assign); // execute immediately
+}
+
+/*****************************************************************************/
+
+/**
+   Slave configuration state: PDO_ASSIGN.
+*/
+
+void ec_fsm_slave_config_state_pdo_assign(
         ec_fsm_slave_config_t *fsm /**< slave state machine */
         )
 {
-    if (ec_fsm_pdo_mapping_exec(&fsm->fsm_pdo_map)) return;
-
-    if (!ec_fsm_pdo_mapping_success(&fsm->fsm_pdo_map)) {
-        EC_ERR("Pdo mapping configuration failed for slave %u.\n",
+    if (ec_fsm_pdo_assign_exec(&fsm->fsm_pdo_assign)) return;
+
+    if (!ec_fsm_pdo_assign_success(&fsm->fsm_pdo_assign)) {
+        EC_ERR("Pdo assignment failed for slave %u.\n",
                 fsm->slave->ring_position);
         fsm->slave->error_flag = 1;
         fsm->state = ec_fsm_slave_config_state_error;
         return;
     }
 
-    // Start Pdo configuration
-    fsm->state = ec_fsm_slave_config_state_pdo_conf;
-    ec_fsm_pdo_config_start(&fsm->fsm_pdo_conf, fsm->slave);
-    ec_fsm_pdo_config_exec(&fsm->fsm_pdo_conf); // execute immediately
-}
-
-/*****************************************************************************/
-
-/**
-   Slave configuration state: PDO_CONF.
-*/
-
-void ec_fsm_slave_config_state_pdo_conf(
+    // Start configuring Pdo mapping
+    fsm->state = ec_fsm_slave_config_state_pdo_mapping;
+    ec_fsm_pdo_mapping_start(&fsm->fsm_pdo_mapping, fsm->slave);
+    ec_fsm_pdo_mapping_exec(&fsm->fsm_pdo_mapping); // execute immediately
+}
+
+/*****************************************************************************/
+
+/**
+   Slave configuration state: PDO_MAPPING.
+*/
+
+void ec_fsm_slave_config_state_pdo_mapping(
         ec_fsm_slave_config_t *fsm /**< slave state machine */
         )
 {
-    if (ec_fsm_pdo_config_exec(&fsm->fsm_pdo_conf)) return;
-
-    if (!ec_fsm_pdo_config_success(&fsm->fsm_pdo_conf)) {
-        EC_ERR("Pdo configuration failed for slave %u.\n",
+    if (ec_fsm_pdo_mapping_exec(&fsm->fsm_pdo_mapping)) return;
+
+    if (!ec_fsm_pdo_mapping_success(&fsm->fsm_pdo_mapping)) {
+        EC_ERR("Configuration of Pdo mapping failed for slave %u.\n",
                 fsm->slave->ring_position);
         fsm->slave->error_flag = 1;
         fsm->state = ec_fsm_slave_config_state_error;
@@ -592,7 +592,7 @@
     for (i = 0; i < num_syncs; i++) {
         sync = &slave->sii.syncs[i + offset];
         dir = ec_sync_direction(sync);
-        size = ec_pdo_mapping_total_size(&slave->config->mapping[dir]);
+        size = ec_pdo_list_total_size(&slave->config->pdos[dir]);
         ec_sync_config(sync, size, datagram->data + EC_SYNC_PAGE_SIZE * i);
     }
 
--- a/master/fsm_slave_config.h	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/fsm_slave_config.h	Thu Apr 03 13:34:13 2008 +0000
@@ -48,8 +48,8 @@
 #include "datagram.h"
 #include "fsm_change.h"
 #include "fsm_coe.h"
+#include "fsm_pdo_assign.h"
 #include "fsm_pdo_mapping.h"
-#include "fsm_pdo_config.h"
 
 /*****************************************************************************/
 
@@ -68,8 +68,8 @@
     ec_sdo_request_t *request; /**< Sdo request for Sdo configuration. */
     ec_fsm_change_t fsm_change; /**< State change state machine. */
     ec_fsm_coe_t fsm_coe; /**< CoE state machine. */
-    ec_fsm_pdo_mapping_t fsm_pdo_map; /**< Pdo mapping state machine. */
-    ec_fsm_pdo_config_t fsm_pdo_conf; /**< Pdo configuration state machine. */
+    ec_fsm_pdo_assign_t fsm_pdo_assign; /**< Pdo assignment state machine. */
+    ec_fsm_pdo_mapping_t fsm_pdo_mapping; /**< Pdo mapping state machine. */
 };
 
 /*****************************************************************************/
--- a/master/fsm_slave_scan.h	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/fsm_slave_scan.h	Thu Apr 03 13:34:13 2008 +0000
@@ -50,8 +50,6 @@
 #include "fsm_change.h"
 #include "fsm_coe.h"
 #include "fsm_coe_map.h"
-#include "fsm_pdo_mapping.h"
-#include "fsm_pdo_config.h"
 
 /*****************************************************************************/
 
--- a/master/master.c	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/master.c	Thu Apr 03 13:34:13 2008 +0000
@@ -1510,7 +1510,7 @@
 
         // try to find the addressed slave
         ec_slave_config_attach(sc);
-        ec_slave_config_load_default_mapping(sc);
+        ec_slave_config_load_default_assignment(sc);
 
         list_add_tail(&sc->list, &master->configs);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/pdo_list.c	Thu Apr 03 13:34:13 2008 +0000
@@ -0,0 +1,280 @@
+/******************************************************************************
+ *
+ *  $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 Pdo list methods.
+*/
+
+/*****************************************************************************/
+
+#include <linux/module.h>
+
+#include "globals.h"
+#include "pdo.h"
+#include "slave_config.h"
+#include "master.h"
+
+#include "pdo_list.h"
+
+/*****************************************************************************/
+
+/** Pdo list constructor.
+ */
+void ec_pdo_list_init(
+        ec_pdo_list_t *pl /**< Pdo list. */
+        )
+{
+    INIT_LIST_HEAD(&pl->list);
+}
+
+/*****************************************************************************/
+
+/** Pdo list destructor.
+ */
+void ec_pdo_list_clear(ec_pdo_list_t *pl /**< Pdo list. */)
+{
+    ec_pdo_list_clear_pdos(pl);
+}
+
+/*****************************************************************************/
+
+/** Clears the list of mapped Pdos.
+ */
+void ec_pdo_list_clear_pdos(ec_pdo_list_t *pl /**< Pdo list. */)
+{
+    ec_pdo_t *pdo, *next;
+
+    list_for_each_entry_safe(pdo, next, &pl->list, list) {
+        list_del_init(&pdo->list);
+        ec_pdo_clear(pdo);
+        kfree(pdo);
+    }
+}
+
+/*****************************************************************************/
+
+/** Calculates the total size of the mapped Pdo entries.
+ *
+ * \retval Data size in byte.
+ */
+uint16_t ec_pdo_list_total_size(
+        const ec_pdo_list_t *pl /**< Pdo list. */
+        )
+{
+    unsigned int bit_size;
+    const ec_pdo_t *pdo;
+    const ec_pdo_entry_t *pdo_entry;
+    uint16_t byte_size;
+
+    bit_size = 0;
+    list_for_each_entry(pdo, &pl->list, list) {
+        list_for_each_entry(pdo_entry, &pdo->entries, list) {
+            bit_size += pdo_entry->bit_length;
+        }
+    }
+
+    if (bit_size % 8) // round up to full bytes
+        byte_size = bit_size / 8 + 1;
+    else
+        byte_size = bit_size / 8;
+
+    return byte_size;
+}
+
+/*****************************************************************************/
+
+/** Add a new Pdo to the list.
+ *
+ * \retval >0 Pointer to new Pdo.
+ * \retval NULL No memory.
+ */
+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. */
+        )
+{
+    ec_pdo_t *pdo;
+
+    if (!(pdo = (ec_pdo_t *) kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
+        EC_ERR("Failed to allocate memory for Pdo.\n");
+        return NULL;
+    }
+
+    ec_pdo_init(pdo);
+    pdo->dir = dir;
+    pdo->index = index;
+    list_add_tail(&pdo->list, &pl->list);
+    return pdo;
+}
+
+/*****************************************************************************/
+
+/** Add the copy of an existing Pdo to the list.
+ *
+ * \return 0 on success, else < 0
+ */
+int ec_pdo_list_add_pdo_copy(
+        ec_pdo_list_t *pl, /**< Pdo list. */
+        const ec_pdo_t *pdo /**< Pdo to add. */
+        )
+{
+    ec_pdo_t *mapped_pdo;
+
+    // Pdo already mapped?
+    list_for_each_entry(mapped_pdo, &pl->list, list) {
+        if (mapped_pdo->index != pdo->index) continue;
+        EC_ERR("Pdo 0x%04X is already mapped!\n", pdo->index);
+        return -1;
+    }
+    
+    if (!(mapped_pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
+        EC_ERR("Failed to allocate Pdo memory.\n");
+        return -1;
+    }
+
+    if (ec_pdo_init_copy(mapped_pdo, pdo)) {
+        kfree(mapped_pdo);
+        return -1;
+    }
+
+    list_add_tail(&mapped_pdo->list, &pl->list);
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Makes a deep copy of another Pdo list.
+ *
+ * \return 0 on success, else < 0
+ */
+int ec_pdo_list_copy(
+        ec_pdo_list_t *pl, /**< Pdo list. */
+        const ec_pdo_list_t *other /**< Pdo list to copy from. */
+        )
+{
+    ec_pdo_t *other_pdo;
+
+    ec_pdo_list_clear_pdos(pl);
+
+    // Pdo already mapped?
+    list_for_each_entry(other_pdo, &other->list, list) {
+        if (ec_pdo_list_add_pdo_copy(pl, other_pdo))
+            return -1;
+    }
+    
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Compares two Pdo lists.
+ *
+ * Only the list is compared, not the Pdo entries (i. e. the Pdo
+ * configuration).
+ *
+ * \retval 1 The given Pdo lists are equal.
+ * \retval 0 The given Pdo lists differ.
+ */
+int ec_pdo_list_equal(
+        const ec_pdo_list_t *pl1, /**< First list. */
+        const ec_pdo_list_t *pl2 /**< Second list. */
+        )
+{
+    const struct list_head *h1, *h2, *l1, *l2;
+    const ec_pdo_t *p1, *p2;
+
+    h1 = l1 = &pl1->list;
+    h2 = l2 = &pl2->list;
+
+    while (1) {
+        l1 = l1->next;
+        l2 = l2->next;
+
+        if ((l1 == h1) ^ (l2 == h2)) // unequal lengths
+            return 0;
+        if (l1 == h1) // both finished
+            break;
+
+        p1 = list_entry(l1, ec_pdo_t, list);
+        p2 = list_entry(l2, ec_pdo_t, list);
+
+        if (p1->index != p2->index)
+            return 0;
+    }
+
+    return 1;
+}
+
+/*****************************************************************************/
+
+/** Finds a Pdo with the given index.
+ */
+ec_pdo_t *ec_pdo_list_find_pdo(
+        const ec_pdo_list_t *pl, /**< Pdo list. */
+        uint16_t index /**< Pdo index. */
+        )
+{
+    ec_pdo_t *pdo;
+
+    list_for_each_entry(pdo, &pl->list, list) {
+        if (pdo->index != index)
+            continue;
+        return pdo;
+    }
+
+    return NULL;
+}
+
+/*****************************************************************************/
+
+/** Finds a Pdo with the given index and returns a const pointer.
+ */
+const ec_pdo_t *ec_pdo_list_find_pdo_const(
+        const ec_pdo_list_t *pl, /**< Pdo list. */
+        uint16_t index /**< Pdo index. */
+        )
+{
+    const ec_pdo_t *pdo;
+
+    list_for_each_entry(pdo, &pl->list, list) {
+        if (pdo->index != index)
+            continue;
+        return pdo;
+    }
+
+    return NULL;
+}
+
+/*****************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/pdo_list.h	Thu Apr 03 13:34:13 2008 +0000
@@ -0,0 +1,81 @@
+/******************************************************************************
+ *
+ *  $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 Pdo list structure.
+*/
+
+/*****************************************************************************/
+
+#ifndef _EC_PDO_LIST_H_
+#define _EC_PDO_LIST_H_
+
+#include <linux/list.h>
+
+#include "../include/ecrt.h"
+
+#include "globals.h"
+#include "pdo.h"
+
+/*****************************************************************************/
+
+/** EtherCAT Pdo list.
+ */
+typedef struct {
+    struct list_head list; /**< List of Pdos. */
+} ec_pdo_list_t;
+
+/*****************************************************************************/
+
+void ec_pdo_list_init(ec_pdo_list_t *);
+void ec_pdo_list_clear(ec_pdo_list_t *);
+
+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);
+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 *);
+
+uint16_t ec_pdo_list_total_size(const ec_pdo_list_t *);
+int ec_pdo_list_equal(const ec_pdo_list_t *, const ec_pdo_list_t *);
+
+ec_pdo_t *ec_pdo_list_find_pdo(const ec_pdo_list_t *, uint16_t);
+const ec_pdo_t *ec_pdo_list_find_pdo_const(const ec_pdo_list_t *,
+        uint16_t);
+
+/*****************************************************************************/
+
+#endif
--- a/master/pdo_mapping.c	Mon Mar 31 09:42:37 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,281 +0,0 @@
-/******************************************************************************
- *
- *  $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 Pdo mapping methods.
-*/
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-
-#include "globals.h"
-#include "pdo.h"
-#include "slave_config.h"
-#include "master.h"
-
-#include "pdo_mapping.h"
-
-/*****************************************************************************/
-
-/** Pdo mapping constructor.
- */
-void ec_pdo_mapping_init(
-        ec_pdo_mapping_t *pm /**< Pdo mapping. */
-        )
-{
-    INIT_LIST_HEAD(&pm->pdos);
-    pm->default_mapping = 1;
-}
-
-/*****************************************************************************/
-
-/** Pdo mapping destructor.
- */
-void ec_pdo_mapping_clear(ec_pdo_mapping_t *pm /**< Pdo mapping. */)
-{
-    ec_pdo_mapping_clear_pdos(pm);
-}
-
-/*****************************************************************************/
-
-/** Clears the list of mapped Pdos.
- */
-void ec_pdo_mapping_clear_pdos(ec_pdo_mapping_t *pm /**< Pdo mapping. */)
-{
-    ec_pdo_t *pdo, *next;
-
-    list_for_each_entry_safe(pdo, next, &pm->pdos, list) {
-        list_del_init(&pdo->list);
-        ec_pdo_clear(pdo);
-        kfree(pdo);
-    }
-}
-
-/*****************************************************************************/
-
-/** Calculates the total size of the mapped Pdo entries.
- *
- * \retval Data size in byte.
- */
-uint16_t ec_pdo_mapping_total_size(
-        const ec_pdo_mapping_t *pm /**< Pdo mapping. */
-        )
-{
-    unsigned int bit_size;
-    const ec_pdo_t *pdo;
-    const ec_pdo_entry_t *pdo_entry;
-    uint16_t byte_size;
-
-    bit_size = 0;
-    list_for_each_entry(pdo, &pm->pdos, list) {
-        list_for_each_entry(pdo_entry, &pdo->entries, list) {
-            bit_size += pdo_entry->bit_length;
-        }
-    }
-
-    if (bit_size % 8) // round up to full bytes
-        byte_size = bit_size / 8 + 1;
-    else
-        byte_size = bit_size / 8;
-
-    return byte_size;
-}
-
-/*****************************************************************************/
-
-/** Add a new Pdo to the mapping.
- *
- * \retval >0 Pointer to new Pdo.
- * \retval NULL No memory.
- */
-ec_pdo_t *ec_pdo_mapping_add_pdo(
-        ec_pdo_mapping_t *pm, /**< Pdo mapping. */
-        ec_direction_t dir, /**< Direction. */
-        uint16_t index /**< Pdo index. */
-        )
-{
-    ec_pdo_t *pdo;
-
-    if (!(pdo = (ec_pdo_t *) kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
-        EC_ERR("Failed to allocate memory for Pdo.\n");
-        return NULL;
-    }
-
-    ec_pdo_init(pdo);
-    pdo->dir = dir;
-    pdo->index = index;
-    list_add_tail(&pdo->list, &pm->pdos);
-    return pdo;
-}
-
-/*****************************************************************************/
-
-/** Add the copy of an existing Pdo to the mapping.
- *
- * \return 0 on success, else < 0
- */
-int ec_pdo_mapping_add_pdo_copy(
-        ec_pdo_mapping_t *pm, /**< Pdo mapping. */
-        const ec_pdo_t *pdo /**< Pdo to add. */
-        )
-{
-    ec_pdo_t *mapped_pdo;
-
-    // Pdo already mapped?
-    list_for_each_entry(mapped_pdo, &pm->pdos, list) {
-        if (mapped_pdo->index != pdo->index) continue;
-        EC_ERR("Pdo 0x%04X is already mapped!\n", pdo->index);
-        return -1;
-    }
-    
-    if (!(mapped_pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
-        EC_ERR("Failed to allocate Pdo memory.\n");
-        return -1;
-    }
-
-    if (ec_pdo_init_copy(mapped_pdo, pdo)) {
-        kfree(mapped_pdo);
-        return -1;
-    }
-
-    list_add_tail(&mapped_pdo->list, &pm->pdos);
-    return 0;
-}
-
-/*****************************************************************************/
-
-/** Makes a deep copy of another Pdo mapping.
- *
- * \return 0 on success, else < 0
- */
-int ec_pdo_mapping_copy(
-        ec_pdo_mapping_t *pm, /**< Pdo mapping. */
-        const ec_pdo_mapping_t *other /**< Pdo mapping to copy from. */
-        )
-{
-    ec_pdo_t *other_pdo;
-
-    ec_pdo_mapping_clear_pdos(pm);
-
-    // Pdo already mapped?
-    list_for_each_entry(other_pdo, &other->pdos, list) {
-        if (ec_pdo_mapping_add_pdo_copy(pm, other_pdo))
-            return -1;
-    }
-    
-    return 0;
-}
-
-/*****************************************************************************/
-
-/** Compares two Pdo mappings.
- *
- * Only the mapping is compared, not the Pdo entries (i. e. the Pdo
- * configuration).
- *
- * \retval 1 The given Pdo mappings are equal.
- * \retval 0 The given Pdo mappings differ.
- */
-int ec_pdo_mapping_equal(
-        const ec_pdo_mapping_t *pm1, /**< First mapping. */
-        const ec_pdo_mapping_t *pm2 /**< Second mapping. */
-        )
-{
-    const struct list_head *h1, *h2, *l1, *l2;
-    const ec_pdo_t *p1, *p2;
-
-    h1 = l1 = &pm1->pdos;
-    h2 = l2 = &pm2->pdos;
-
-    while (1) {
-        l1 = l1->next;
-        l2 = l2->next;
-
-        if ((l1 == h1) ^ (l2 == h2)) // unequal lengths
-            return 0;
-        if (l1 == h1) // both finished
-            break;
-
-        p1 = list_entry(l1, ec_pdo_t, list);
-        p2 = list_entry(l2, ec_pdo_t, list);
-
-        if (p1->index != p2->index)
-            return 0;
-    }
-
-    return 1;
-}
-
-/*****************************************************************************/
-
-/** Finds a Pdo with the given index.
- */
-ec_pdo_t *ec_pdo_mapping_find_pdo(
-        const ec_pdo_mapping_t *pm, /**< Pdo mapping. */
-        uint16_t index /**< Pdo index. */
-        )
-{
-    ec_pdo_t *pdo;
-
-    list_for_each_entry(pdo, &pm->pdos, list) {
-        if (pdo->index != index)
-            continue;
-        return pdo;
-    }
-
-    return NULL;
-}
-
-/*****************************************************************************/
-
-/** Finds a Pdo with the given index and returns a const pointer.
- */
-const ec_pdo_t *ec_pdo_mapping_find_pdo_const(
-        const ec_pdo_mapping_t *pm, /**< Pdo mapping. */
-        uint16_t index /**< Pdo index. */
-        )
-{
-    const ec_pdo_t *pdo;
-
-    list_for_each_entry(pdo, &pm->pdos, list) {
-        if (pdo->index != index)
-            continue;
-        return pdo;
-    }
-
-    return NULL;
-}
-
-/*****************************************************************************/
--- a/master/pdo_mapping.h	Mon Mar 31 09:42:37 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/******************************************************************************
- *
- *  $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 Pdo mapping structure.
-*/
-
-/*****************************************************************************/
-
-#ifndef _EC_PDO_MAPPING_H_
-#define _EC_PDO_MAPPING_H_
-
-#include <linux/list.h>
-
-#include "../include/ecrt.h"
-
-#include "globals.h"
-#include "pdo.h"
-
-/*****************************************************************************/
-
-/** EtherCAT Pdo mapping.
- */
-typedef struct {
-    struct list_head pdos; /**< List of Pdos. */
-    unsigned int default_mapping; /**< This is the default mapping. */
-} ec_pdo_mapping_t;
-
-/*****************************************************************************/
-
-void ec_pdo_mapping_init(ec_pdo_mapping_t *);
-void ec_pdo_mapping_clear(ec_pdo_mapping_t *);
-
-void ec_pdo_mapping_clear_pdos(ec_pdo_mapping_t *);
-
-ec_pdo_t *ec_pdo_mapping_add_pdo(ec_pdo_mapping_t *, ec_direction_t,
-        uint16_t);
-int ec_pdo_mapping_add_pdo_copy(ec_pdo_mapping_t *, const ec_pdo_t *);
-
-int ec_pdo_mapping_copy(ec_pdo_mapping_t *, const ec_pdo_mapping_t *);
-
-uint16_t ec_pdo_mapping_total_size(const ec_pdo_mapping_t *);
-int ec_pdo_mapping_equal(const ec_pdo_mapping_t *, const ec_pdo_mapping_t *);
-
-ec_pdo_t *ec_pdo_mapping_find_pdo(const ec_pdo_mapping_t *, uint16_t);
-const ec_pdo_t *ec_pdo_mapping_find_pdo_const(const ec_pdo_mapping_t *,
-        uint16_t);
-
-/*****************************************************************************/
-
-#endif
--- a/master/slave.c	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/slave.c	Thu Apr 03 13:34:13 2008 +0000
@@ -615,10 +615,10 @@
             }
             sync = &slave->sii.syncs[pdo->sync_index];
 
-            if (ec_pdo_mapping_add_pdo_copy(&sync->mapping, pdo))
+            if (ec_pdo_list_add_pdo_copy(&sync->pdos, pdo))
                 return -1;
 
-            sync->mapping_source = EC_SYNC_MAPPING_SII;
+            sync->assign_source = EC_ASSIGN_SII;
         }
     }
 
@@ -798,7 +798,7 @@
     }
 
     if (slave->sii.sync_count) {
-        buf += sprintf(buf, "Sync managers / Pdo mapping:\n");
+        buf += sprintf(buf, "Sync managers / assigned Pdos:\n");
 
         for (i = 0; i < slave->sii.sync_count; i++) {
             sync = &slave->sii.syncs[i];
@@ -808,16 +808,28 @@
                     sync->length, sync->control_register,
                     sync->enable ? "enable" : "disable");
 
-            if (list_empty(&sync->mapping.pdos)) {
-                buf += sprintf(buf, "    No Pdos mapped.\n");
-            } else if (sync->mapping_source != EC_SYNC_MAPPING_NONE) {
-                buf += sprintf(buf,
-                        "    Pdo mapping information from %s.\n",
-                        sync->mapping_source == EC_SYNC_MAPPING_SII
-                        ? "SII" : "CoE");
+            if (list_empty(&sync->pdos.list)) {
+                buf += sprintf(buf, "    No Pdos assigned.\n");
+            } else if (sync->assign_source != EC_ASSIGN_NONE) {
+                buf += sprintf(buf, "    Pdo assignment from ");
+                switch (sync->assign_source) {
+                    case EC_ASSIGN_SII:
+                        buf += sprintf(buf, "SII");
+                        break;
+                    case EC_ASSIGN_COE:
+                        buf += sprintf(buf, "CoE");
+                        break;
+                    case EC_ASSIGN_CUSTOM:
+                        buf += sprintf(buf, "application");
+                        break;
+                    default:
+                        buf += sprintf(buf, "?");
+                        break;
+                }
+                buf += sprintf(buf, ".\n");
             }
 
-            list_for_each_entry(pdo, &sync->mapping.pdos, list) {
+            list_for_each_entry(pdo, &sync->pdos.list, list) {
                 buf += sprintf(buf, "    %s 0x%04X \"%s\"\n",
                         pdo->dir == EC_DIR_OUTPUT ? "RxPdo" : "TxPdo",
                         pdo->index, pdo->name ? pdo->name : "???");
@@ -843,10 +855,10 @@
                     pdo->dir == EC_DIR_OUTPUT ? "RxPdo" : "TxPdo",
                     pdo->index, pdo->name ? pdo->name : "???");
             if (pdo->sync_index >= 0)
-                buf += sprintf(buf, ", default mapping: SM%u.\n",
+                buf += sprintf(buf, ", default assignment: SM%u.\n",
                         pdo->sync_index);
             else
-                buf += sprintf(buf, ", no default mapping.\n");
+                buf += sprintf(buf, ", no default assignment.\n");
 
             list_for_each_entry(pdo_entry, &pdo->entries, list) {
                 buf += sprintf(buf, "    0x%04X:%X \"%s\", %u bit\n",
@@ -1302,7 +1314,7 @@
     for (i = 0; i < slave->sii.sync_count; i++) {
         sync = &slave->sii.syncs[i];
 
-        if (!(pdo = ec_pdo_mapping_find_pdo_const(&sync->mapping, index)))
+        if (!(pdo = ec_pdo_list_find_pdo_const(&sync->pdos, index)))
             continue;
 
         return pdo;
--- a/master/slave_config.c	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/slave_config.c	Thu Apr 03 13:34:13 2008 +0000
@@ -102,7 +102,7 @@
     sc->slave = NULL;
 
     for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
-        ec_pdo_mapping_init(&sc->mapping[dir]);
+        ec_pdo_list_init(&sc->pdos[dir]);
 
     INIT_LIST_HEAD(&sc->sdo_configs);
     INIT_LIST_HEAD(&sc->sdo_requests);
@@ -166,7 +166,7 @@
 
     // Free Pdo mappings
     for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
-        ec_pdo_mapping_clear(&sc->mapping[dir]);
+        ec_pdo_list_clear(&sc->pdos[dir]);
 
     // free all Sdo configurations
     list_for_each_entry_safe(req, next_req, &sc->sdo_configs, list) {
@@ -236,7 +236,7 @@
 {
     char *buf = buffer;
     ec_direction_t dir;
-    const ec_pdo_mapping_t *map;
+    const ec_pdo_list_t *pdos;
     const ec_pdo_t *pdo;
     const ec_pdo_entry_t *entry;
     char str[20];
@@ -246,13 +246,13 @@
     buf += sprintf(buf, "Position: %u\n", sc->position);
 
     for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) {
-        map = &sc->mapping[dir];
+        pdos = &sc->pdos[dir];
         
-        if (!list_empty(&map->pdos)) {
-            buf += sprintf(buf, "%s mapping:\n",
+        if (!list_empty(&pdos->list)) {
+            buf += sprintf(buf, "%s Pdo assignment / mapping:\n",
                     dir == EC_DIR_OUTPUT ? "Output" : "Input");
 
-            list_for_each_entry(pdo, &map->pdos, list) {
+            list_for_each_entry(pdo, &pdos->list, list) {
                 buf += sprintf(buf, "  %s 0x%04X \"%s\"\n",
                         pdo->dir == EC_DIR_OUTPUT ? "RxPdo" : "TxPdo",
                         pdo->index, pdo->name ? pdo->name : "???");
@@ -429,31 +429,29 @@
 
 /*****************************************************************************/
 
-/** Loads the default mapping from the slave object.
- */
-void ec_slave_config_load_default_mapping(ec_slave_config_t *sc)
+/** 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_mapping_t *map;
+    ec_pdo_list_t *pdos;
     ec_sync_t *sync;
 
     if (!sc->slave)
         return;
     
     for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) {
-        map = &sc->mapping[dir];
-        if (!(sync = ec_slave_get_pdo_sync(sc->slave, dir)))
-            continue;
-        ec_pdo_mapping_copy(map, &sync->mapping);
-        map->default_mapping = 1;
-    }
-}
-
-/*****************************************************************************/
-
-/** Loads the default configuration for a Pdo from the slave object.
- */
-void ec_slave_config_load_default_pdo_config(
+        pdos = &sc->pdos[dir];
+        if ((sync = ec_slave_get_pdo_sync(sc->slave, dir)))
+            ec_pdo_list_copy(pdos, &sync->pdos);
+    }
+}
+
+/*****************************************************************************/
+
+/** Loads the default mapping for a Pdo from the slave object.
+ */
+void ec_slave_config_load_default_mapping(
         const ec_slave_config_t *sc,
         ec_pdo_t *pdo
         )
@@ -479,7 +477,7 @@
         return;
     }
 
-    list_for_each_entry(default_pdo, &sync->mapping.pdos, list) {
+    list_for_each_entry(default_pdo, &sync->pdos.list, list) {
         if (default_pdo->index != pdo->index)
             continue;
 
@@ -508,113 +506,128 @@
  *  Realtime interface
  *****************************************************************************/
 
-int ecrt_slave_config_pdo(ec_slave_config_t *sc, ec_direction_t dir,
-        uint16_t index)
-{
-    ec_pdo_mapping_t *pm = &sc->mapping[dir];
+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];
     ec_pdo_t *pdo;
     
-    if (pm->default_mapping) {
-        if (sc->master->debug_level)
-            EC_DBG("Clearing default mapping for dir %u, config %u:%u.\n",
-                    dir, sc->alias, sc->position);
-        pm->default_mapping = 0;
-        ec_pdo_mapping_clear_pdos(pm);
-    }
-
     if (sc->master->debug_level)
-        EC_DBG("Adding Pdo 0x%04X to mapping for dir %u, config %u:%u.\n",
+        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_mapping_add_pdo(pm, dir, index)))
+    if (!(pdo = ec_pdo_list_add_pdo(pl, dir, index)))
         return -1;
 
-    ec_slave_config_load_default_pdo_config(sc, pdo);
+    ec_slave_config_load_default_mapping(sc, pdo);
     return 0;
 }
 
 /*****************************************************************************/
 
-int ecrt_slave_config_pdo_entry(ec_slave_config_t *sc, uint16_t pdo_index,
-        uint16_t entry_index, uint8_t entry_subindex,
+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]);
+}
+
+/*****************************************************************************/
+
+int ecrt_slave_config_pdo_mapping_add(ec_slave_config_t *sc,
+        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;
     
     if (sc->master->debug_level)
-        EC_DBG("Adding Pdo entry 0x%04X:%u (%u bit) to configuration of Pdo"
+        EC_DBG("Adding Pdo entry 0x%04X:%u (%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_mapping_find_pdo(&sc->mapping[dir], pdo_index)))
+        if ((pdo = ec_pdo_list_find_pdo(&sc->pdos[dir], pdo_index)))
             break;
 
     if (!pdo) {
-        EC_ERR("Pdo 0x%04X was not found in the mapping of config %u:%u.\n",
+        EC_ERR("Pdo 0x%04X is not assigned in config %u:%u.\n",
                 pdo_index, sc->alias, sc->position);
         return -1;
     }
 
-    if (pdo->default_config) {
-        if (sc->master->debug_level)
-            EC_DBG("Clearing default configuration of Pdo 0x%04X,"
-                    " config %u:%u.\n", pdo->index, sc->alias, sc->position);
-        pdo->default_config = 0;
-        ec_pdo_clear_entries(pdo);
-    }
-
     return ec_pdo_add_entry(pdo, entry_index, entry_subindex,
             entry_bit_length) ? 0 : -1;
 }
 
 /*****************************************************************************/
 
-int ecrt_slave_config_mapping(ec_slave_config_t *sc, unsigned int n_infos,
+void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
+        uint16_t pdo_index)
+{
+    ec_direction_t dir;
+    ec_pdo_t *pdo;
+    
+    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)))
+            break;
+
+    if (!pdo) {
+        EC_WARN("Pdo 0x%04X is not assigned in config %u:%u.\n",
+                pdo_index, sc->alias, sc->position);
+        return;
+    }
+
+    ec_pdo_clear_entries(pdo);
+}
+
+/*****************************************************************************/
+
+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_mapping_t *pm;
-    ec_pdo_t *pdo;
+    ec_pdo_list_t *pl;
+    unsigned int cleared[] = {0, 0};
     const ec_pdo_entry_info_t *ei;
 
     for (i = 0; i < n_infos; i++) {
         pi = &pdo_infos[i];
 
-        if (pi->dir == EC_MAP_END)
+        if (pi->dir == EC_END)
             break;
 
-        pm = &sc->mapping[pi->dir];
-
-        if (pm->default_mapping) {
+        pl = &sc->pdos[pi->dir];
+
+        if (!cleared[pi->dir]) {
+            ecrt_slave_config_pdo_assign_clear(sc, pi->dir);
+            cleared[pi->dir] = 1;
+        }
+
+        if (ecrt_slave_config_pdo_assign_add(sc, pi->dir, pi->index))
+            return -1;
+
+        if (pi->n_entries && pi->entries) { // mapping provided
             if (sc->master->debug_level)
-                EC_DBG("Clearing default mapping for dir %u, config %u:%u.\n",
-                        pi->dir, sc->alias, sc->position);
-            pm->default_mapping = 0;
-            ec_pdo_mapping_clear_pdos(pm);
-        }
-
-        if (sc->master->debug_level)
-            EC_DBG("Adding Pdo 0x%04X to mapping for dir %u, config %u:%u.\n",
-                    pi->index, pi->dir, sc->alias, sc->position);
-
-        if (!(pdo = ec_pdo_mapping_add_pdo(pm, pi->dir, pi->index)))
-            return -1;
-
-        if (pi->n_entries && pi->entries) { // configuration provided
-            if (sc->master->debug_level)
-                EC_DBG("  Pdo configuration information provided.\n");
+                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 (!ec_pdo_add_entry(pdo, ei->index, ei->subindex,
-                            ei->bit_length))
+
+                if (ecrt_slave_config_pdo_mapping_add(sc, pi->index,
+                        ei->index, ei->subindex, ei->bit_length))
                     return -1;
             }
-        } else { // use default Pdo configuration
-            ec_slave_config_load_default_pdo_config(sc, pdo);
         }
     }
 
@@ -631,16 +644,16 @@
         )
 {
     ec_direction_t dir;
-    ec_pdo_mapping_t *map;
+    ec_pdo_list_t *pdos;
     unsigned int bit_offset, byte_offset;
     ec_pdo_t *pdo;
     ec_pdo_entry_t *entry;
     int ret;
 
     for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++) {
-        map = &sc->mapping[dir];
+        pdos = &sc->pdos[dir];
         bit_offset = 0;
-        list_for_each_entry(pdo, &map->pdos, list) {
+        list_for_each_entry(pdo, &pdos->list, list) {
             list_for_each_entry(entry, &pdo->entries, list) {
                 if (entry->index != index || entry->subindex != subindex) {
                     bit_offset += entry->bit_length;
@@ -726,9 +739,11 @@
 
 /** \cond */
 
-EXPORT_SYMBOL(ecrt_slave_config_pdo);
-EXPORT_SYMBOL(ecrt_slave_config_pdo_entry);
-EXPORT_SYMBOL(ecrt_slave_config_mapping);
+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_reg_pdo_entry);
 EXPORT_SYMBOL(ecrt_slave_config_sdo8);
 EXPORT_SYMBOL(ecrt_slave_config_sdo16);
--- a/master/slave_config.h	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/slave_config.h	Thu Apr 03 13:34:13 2008 +0000
@@ -49,7 +49,7 @@
 #include "globals.h"
 #include "slave.h"
 #include "fmmu_config.h"
-#include "pdo_mapping.h"
+#include "pdo_list.h"
 
 /*****************************************************************************/
 
@@ -69,7 +69,7 @@
     ec_slave_t *slave; /**< Slave pointer. This is \a NULL, if the slave is
                          offline. */
 
-    ec_pdo_mapping_t mapping[2]; /**< Output and input Pdo mapping. */
+    ec_pdo_list_t pdos[2]; /**< Output and input Pdo assignment / mapping. */
 
     struct list_head sdo_configs; /**< List of Sdo configurations. */
     struct list_head sdo_requests; /**< List of Sdo requests. */
@@ -87,8 +87,8 @@
 int ec_slave_config_attach(ec_slave_config_t *);
 void ec_slave_config_detach(ec_slave_config_t *);
 
-void ec_slave_config_load_default_mapping(ec_slave_config_t *);
-void ec_slave_config_load_default_pdo_config(const 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 *);
 
 /*****************************************************************************/
--- a/master/sync.c	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/sync.c	Thu Apr 03 13:34:13 2008 +0000
@@ -56,8 +56,8 @@
     sync->slave = slave;
     sync->index = index;    
 
-    ec_pdo_mapping_init(&sync->mapping);
-    sync->mapping_source = EC_SYNC_MAPPING_NONE;
+    ec_pdo_list_init(&sync->pdos);
+    sync->assign_source = EC_ASSIGN_NONE;
 }
 
 /*****************************************************************************/
@@ -76,10 +76,10 @@
    sync->control_register = other->control_register;
    sync->enable = other->enable;
    
-   ec_pdo_mapping_init(&sync->mapping);
-   ec_pdo_mapping_copy(&sync->mapping, &other->mapping);
+   ec_pdo_list_init(&sync->pdos);
+   ec_pdo_list_copy(&sync->pdos, &other->pdos);
 
-   sync->mapping_source = other->mapping_source;
+   sync->assign_source = other->assign_source;
 }
 
 /*****************************************************************************/
@@ -90,7 +90,7 @@
         ec_sync_t *sync /**< EtherCAT sync manager. */
         )
 {
-    ec_pdo_mapping_clear(&sync->mapping);
+    ec_pdo_list_clear(&sync->pdos);
 }
 
 /*****************************************************************************/
@@ -129,7 +129,7 @@
         const ec_pdo_t *pdo /**< Pdo to map. */
         )
 {
-    return ec_pdo_mapping_add_pdo_copy(&sync->mapping, pdo);
+    return ec_pdo_list_add_pdo_copy(&sync->pdos, pdo);
 }
 
 /*****************************************************************************/
--- a/master/sync.h	Mon Mar 31 09:42:37 2008 +0000
+++ b/master/sync.h	Thu Apr 03 13:34:13 2008 +0000
@@ -45,18 +45,18 @@
 #include "../include/ecrt.h"
 
 #include "globals.h"
-#include "pdo_mapping.h"
+#include "pdo_list.h"
 
 /*****************************************************************************/
 
-/** EtherCAT sync manager Pdo mapping information source.
+/** EtherCAT Pdo assignment source.
  */
 typedef enum {
-    EC_SYNC_MAPPING_NONE, /**< No Pdo mapping information. */
-    EC_SYNC_MAPPING_SII, /**< Pdo mapping information from SII. */
-    EC_SYNC_MAPPING_COE, /**< Pdo mapping information from CoE dictionary. */
-    EC_SYNC_MAPPING_CUSTOM, /**< Pdo mapping configured externally. */
-} ec_sync_mapping_source_t;
+    EC_ASSIGN_NONE, /**< No Pdos assigned. */
+    EC_ASSIGN_SII, /**< Pdo assignment read from SII. */
+    EC_ASSIGN_COE, /**< Pdo assignment read via CoE. */
+    EC_ASSIGN_CUSTOM, /**< Pdos assignment set by application. */
+} ec_assign_source_t;
 
 /*****************************************************************************/
 
@@ -69,8 +69,8 @@
     uint16_t length; /**< Data length in bytes. */
     uint8_t control_register; /**< Control register value. */
     uint8_t enable; /**< Enable bit. */
-    ec_pdo_mapping_t mapping; /**< Current Pdo mapping. */
-    ec_sync_mapping_source_t mapping_source; /**< Pdo mapping source. */
+    ec_pdo_list_t pdos; /**< Current Pdo assignment. */
+    ec_assign_source_t assign_source; /**< Pdo assignment source. */
 } ec_sync_t;
 
 /*****************************************************************************/