Added ecrt_slave_config_pdo() and ecrt_slave_config_pdo_entry().
authorFlorian Pose <fp@igh-essen.com>
Thu, 28 Feb 2008 14:29:50 +0000
changeset 842 40e27e5a8dce
parent 841 6f0cf00d7107
child 843 b6bddb663755
Added ecrt_slave_config_pdo() and ecrt_slave_config_pdo_entry().
NEWS
include/ecrt.h
master/pdo.c
master/pdo.h
master/pdo_mapping.c
master/pdo_mapping.h
master/slave_config.c
master/slave_config.h
--- a/NEWS	Thu Feb 28 14:18:37 2008 +0000
+++ b/NEWS	Thu Feb 28 14:29:50 2008 +0000
@@ -17,7 +17,7 @@
     - Added ec_slave_config_state_t for the new method
       ecrt_slave_config_state().
     - Process data memory for a domain can now be allocated externally. This
-      offers the possibility to use a shared-memory-region. Therefore,
+      offers the possibility to use a shared-memory region. Therefore,
       added the domain methods ecrt_domain_size() and
       ecrt_domain_external_memory().
     - Replaced the process data pointers in the Pdo entry registration
@@ -27,10 +27,11 @@
       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_mapping() that is now able to specify Pdo mapping and
-      Pdo configuration. Pdo entries mapped in this way can now immediately be
-      registered. The Pdo mapping and the configuration are described with the
-      new data types ec_pdo_info_t and ec_pdo_entry_info_t.
+      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.
     - 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.
--- a/include/ecrt.h	Thu Feb 28 14:18:37 2008 +0000
+++ b/include/ecrt.h	Thu Feb 28 14:29:50 2008 +0000
@@ -54,7 +54,7 @@
  * - Added ec_slave_config_state_t for the new method
  *   ecrt_slave_config_state().
  * - Process data memory for a domain can now be allocated externally. This
- *   offers the possibility to use a shared-memory-region. Therefore,
+ *   offers the possibility to use a shared-memory region. Therefore,
  *   added the domain methods ecrt_domain_size() and
  *   ecrt_domain_external_memory().
  * - Replaced the process data pointers in the Pdo entry registration
@@ -64,10 +64,11 @@
  *   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_mapping() that is now able to specify Pdo mapping and
- *   Pdo configuration. Pdo entries mapped in this way can now immediately be
- *   registered. The Pdo mapping and the configuration are described with the
- *   new data types ec_pdo_info_t and ec_pdo_entry_info_t.
+ *   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.
  * - 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.
@@ -370,34 +371,73 @@
  * 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()
+ * \return zero on success, else non-zero
+ */
+int ecrt_slave_config_pdo(
+        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()
+ * \return zero on success, else non-zero
+ */
+int ecrt_slave_config_pdo_entry(
+        ec_slave_config_t *sc, /**< Slave configuration. */
+        uint16_t pdo_index, /**< Index of the Pdo to configure. */
+        uint16_t entry_index, /**< Index of the Pdo entry to add to the Pdo's
+                                configuration. */
+        uint8_t entry_subindex, /**< Subindex of the Pdo entry to add to the
+                                  Pdo's configuration. */
+        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:
  *
  * \code
- * const ec_pdo_info_t complete_mapping[] = {
- *     {EC_DIR_INPUT, 0x1600, 2, { // channel 1
- *         {0x7000, 0, 16}, // value
- *         {0x7000, 1, 8},  // status
- *     }},
- *     {EC_DIR_INPUT, 0x1601, 2, { // channel 2 
- *         {0x7001, 0, 16}, // value
- *         {0x7001, 1, 8},  // status
- *     }}
+ * const ec_pdo_entry_info_t el3162_channel1[] = {
+ *     {0x3101, 1,  8}, // status
+ *     {0x3101, 2, 16}  // value
  * };
  * 
- * if (ecrt_slave_config_mapping(slave_config_ana_in, 2, complete_mapping)) {
- *     // error
- * }
+ * const ec_pdo_entry_info_t el3162_channel2[] = {
+ *     {0x3102, 1,  8}, // status
+ *     {0x3102, 2, 16}  // value
+ * };
+ * 
+ * const ec_pdo_info_t el3162_mapping[] = {
+ *     {EC_DIR_INPUT, 0x1A00, 2, el3162_channel1},
+ *     {EC_DIR_INPUT, 0x1A01, 2, el3162_channel2},
+ * };
+ * 
+ * if (ecrt_slave_config_mapping(sc, 2, el3162_mapping))
+ *     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 no Pdo configuration is
- * specified and the slave is offline.
+ * 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[] = {
@@ -405,9 +445,8 @@
  *     {EC_DIR_INPUT, 0x1601}  // Channel 2
  * };
  * 
- * if (ecrt_slave_config_mapping(slave_config_ana_in, 2, pdo_mapping)) {
- *     // error
- * }
+ * if (ecrt_slave_config_mapping(slave_config_ana_in, 2, pdo_mapping))
+ *     return -1; // error
  * \endcode
  *
  * \return zero on success, else non-zero
@@ -418,15 +457,18 @@
         const ec_pdo_info_t pdos[] /**< List with Pdo mapping. */
         );
 
-/** Registers a Pdo entry of the given slave configuration at a domain.
- *
- * Searches the mapping and the Pdo configurations for the given Pdo entry. If
- * found, the curresponding sync manager/FMMU is added to the domain and the
- * offset of the Pdo entry's data in the domain process data is returned.
- *
- * \retval >=0 Offset of the Pdo entry's process data.
- * \retval -1  Pdo entry not found.
- * \retval -2  Failed to register Pdo entry.
+/** Registers a Pdo entry for process data exchange in a domain.
+ *
+ * Searches the current mapping and Pdo configurations 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.
+ *
+ * \retval >=0 Success: Offset of the Pdo entry's process data.
+ * \retval -1  Error: Pdo entry not found.
+ * \retval -2  Error: Failed to register Pdo entry.
  */
 int ecrt_slave_config_reg_pdo_entry(
         ec_slave_config_t *sc, /**< Slave configuration. */
--- a/master/pdo.c	Thu Feb 28 14:18:37 2008 +0000
+++ b/master/pdo.c	Thu Feb 28 14:29:50 2008 +0000
@@ -44,10 +44,6 @@
 
 /*****************************************************************************/
 
-void ec_pdo_clear_entries(ec_pdo_t *);
-
-/*****************************************************************************/
-
 /** Pdo constructor.
  */
 void ec_pdo_init(
@@ -57,6 +53,7 @@
     pdo->sync_index = -1; // not assigned 
     pdo->name = NULL;
     INIT_LIST_HEAD(&pdo->entries);
+    pdo->default_config = 0;
 }
 
 /*****************************************************************************/
@@ -70,6 +67,7 @@
     pdo->sync_index = other_pdo->sync_index;
     pdo->name = NULL;
     INIT_LIST_HEAD(&pdo->entries);
+    pdo->default_config = other_pdo->default_config;
 
     if (ec_pdo_set_name(pdo, other_pdo->name))
         goto out_return;
@@ -89,7 +87,7 @@
 
 /** Pdo destructor.
  */
-void ec_pdo_clear(ec_pdo_t *pdo /**< EtherCAT Pdo */)
+void ec_pdo_clear(ec_pdo_t *pdo /**< EtherCAT Pdo. */)
 {
     if (pdo->name)
         kfree(pdo->name);
@@ -101,7 +99,7 @@
 
 /** Clear Pdo entry list.
  */
-void ec_pdo_clear_entries(ec_pdo_t *pdo /**< EtherCAT Pdo */)
+void ec_pdo_clear_entries(ec_pdo_t *pdo /**< EtherCAT Pdo. */)
 {
     ec_pdo_entry_t *entry, *next;
 
@@ -142,6 +140,32 @@
 
 /*****************************************************************************/
 
+/** Add a new Pdo entry to the configuration.
+ */
+ec_pdo_entry_t *ec_pdo_add_entry(
+        ec_pdo_t *pdo,
+        uint16_t index,
+        uint8_t subindex,
+        uint8_t bit_length
+        )
+{
+    ec_pdo_entry_t *entry;
+
+    if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
+        EC_ERR("Failed to allocate memory for Pdo entry.\n");
+        return NULL;
+    }
+
+    ec_pdo_entry_init(entry);
+    entry->index = index;
+    entry->subindex = subindex;
+    entry->bit_length = bit_length;
+    list_add_tail(&entry->list, &pdo->entries);
+    return entry;
+}
+
+/*****************************************************************************/
+
 /** Copy Pdo entries from another Pdo.
  */
 int ec_pdo_copy_entries(ec_pdo_t *pdo, const ec_pdo_t *other)
--- a/master/pdo.h	Thu Feb 28 14:18:37 2008 +0000
+++ b/master/pdo.h	Thu Feb 28 14:29:50 2008 +0000
@@ -58,6 +58,8 @@
     int8_t sync_index; /**< Assigned sync manager. */
     char *name; /**< Pdo name. */
     struct list_head entries; /**< List of Pdo entries. */
+    unsigned int default_config; /**< The entries contain the default Pdo
+                                   configuration. */
 } ec_pdo_t;
 
 /*****************************************************************************/
@@ -77,7 +79,9 @@
 void ec_pdo_init(ec_pdo_t *);
 int ec_pdo_init_copy(ec_pdo_t *, const ec_pdo_t *);
 void ec_pdo_clear(ec_pdo_t *);
+void ec_pdo_clear_entries(ec_pdo_t *);
 int ec_pdo_set_name(ec_pdo_t *, const char *);
+ec_pdo_entry_t *ec_pdo_add_entry(ec_pdo_t *, uint16_t, uint8_t, uint8_t);
 int ec_pdo_copy_entries(ec_pdo_t *, const ec_pdo_t *);
 int ec_pdo_equal_entries(const ec_pdo_t *, const ec_pdo_t *);
 
--- a/master/pdo_mapping.c	Thu Feb 28 14:18:37 2008 +0000
+++ b/master/pdo_mapping.c	Thu Feb 28 14:29:50 2008 +0000
@@ -115,7 +115,34 @@
 
 /*****************************************************************************/
 
-/** Adds a Pdo to the mapping.
+/** 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. */
+        uint16_t index, /**< Pdo index. */
+        ec_direction_t dir /**< Direction. */
+        )
+{
+    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
  */
@@ -134,7 +161,7 @@
     }
     
     if (!(mapped_pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
-        EC_ERR("Failed to allocate memory for Pdo mapping.\n");
+        EC_ERR("Failed to allocate Pdo memory.\n");
         return -1;
     }
 
@@ -149,111 +176,6 @@
 
 /*****************************************************************************/
 
-/** Add a Pdo to the mapping.
- *
- * The first call of this method will clear the default mapping.
- *
- * \retval 0 Success.
- * \retval -1 Error.
- */
-int ec_pdo_mapping_add_pdo_info(
-        ec_pdo_mapping_t *pm, /**< Pdo mapping. */
-        const ec_pdo_info_t *pdo_info, /**< Pdo information. */
-        const ec_slave_config_t *config /**< Slave configuration, to load
-                                          default entries. */
-        )
-{
-    unsigned int i;
-    ec_pdo_t *pdo;
-    ec_pdo_entry_t *entry;
-    const ec_pdo_entry_info_t *entry_info;
-
-    if (pm->default_mapping) {
-        pm->default_mapping = 0;
-        ec_pdo_mapping_clear_pdos(pm);
-    }
-
-    if (!(pdo = (ec_pdo_t *) kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
-        EC_ERR("Failed to allocate memory for Pdo.\n");
-        goto out_return;
-    }
-
-    ec_pdo_init(pdo);
-    pdo->dir = pdo_info->dir;
-    pdo->index = pdo_info->index;
-
-    if (config->master->debug_level)
-        EC_INFO("Adding Pdo 0x%04X to mapping.\n", pdo->index);
-
-    if (pdo_info->n_entries && pdo_info->entries) { // configuration provided
-        if (config->master->debug_level)
-            EC_INFO("  Pdo configuration provided.\n");
-
-        for (i = 0; i < pdo_info->n_entries; i++) {
-            entry_info = &pdo_info->entries[i];
-
-            if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
-                EC_ERR("Failed to allocate memory for Pdo entry.\n");
-                goto out_free;
-            }
-
-            ec_pdo_entry_init(entry);
-            entry->index = entry_info->index;
-            entry->subindex = entry_info->subindex;
-            entry->bit_length = entry_info->bit_length;
-            list_add_tail(&entry->list, &pdo->entries);
-        }
-    } else { // use default Pdo configuration
-        if (config->master->debug_level)
-            EC_INFO("  Using default Pdo configuration.\n");
-
-        if (config->slave) {
-            ec_sync_t *sync;
-            ec_pdo_t *default_pdo;
-
-            if ((sync = ec_slave_get_pdo_sync(config->slave, pdo->dir))) {
-                list_for_each_entry(default_pdo, &sync->mapping.pdos, list) {
-                    if (default_pdo->index != pdo->index)
-                        continue;
-                    if (config->master->debug_level)
-                        EC_INFO("  Found Pdo name \"%s\".\n",
-                                default_pdo->name);
-                    // try to take Pdo name from mapped one
-                    if (ec_pdo_set_name(pdo, default_pdo->name))
-                        goto out_free;
-                    // copy entries (= default Pdo configuration)
-                    if (ec_pdo_copy_entries(pdo, default_pdo))
-                        goto out_free;
-                    if (config->master->debug_level) {
-                        const ec_pdo_entry_t *entry;
-                        list_for_each_entry(entry, &pdo->entries, list) {
-                            EC_INFO("    Entry 0x%04X:%u.\n",
-                                    entry->index, entry->subindex);
-                        }
-                    }
-                }
-            } else {
-                EC_WARN("Slave %u does not provide a default Pdo"
-                        " configuration!\n", config->slave->ring_position);
-            }
-        } else {
-            EC_WARN("Failed to load default Pdo configuration for %u:%u:"
-                    " Slave not found.\n", config->alias, config->position);
-        }
-    }
-
-    list_add_tail(&pdo->list, &pm->pdos);
-    return 0;
-
-out_free:
-    ec_pdo_clear(pdo);
-    kfree(pdo);
-out_return:
-    return -1;
-}
-
-/*****************************************************************************/
-
 /** Makes a deep copy of another Pdo mapping.
  *
  * \return 0 on success, else < 0
@@ -318,14 +240,14 @@
 
 /*****************************************************************************/
 
-/** Finds a Pdo with the given index and returns a const pointer.
- */
-const ec_pdo_t *ec_pdo_mapping_find_pdo_const(
+/** 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. */
         )
 {
-    const ec_pdo_t *pdo;
+    ec_pdo_t *pdo;
 
     list_for_each_entry(pdo, &pm->pdos, list) {
         if (pdo->index != index)
@@ -337,3 +259,23 @@
 }
 
 /*****************************************************************************/
+
+/** 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	Thu Feb 28 14:18:37 2008 +0000
+++ b/master/pdo_mapping.h	Thu Feb 28 14:29:50 2008 +0000
@@ -64,15 +64,16 @@
 
 void ec_pdo_mapping_clear_pdos(ec_pdo_mapping_t *);
 
+ec_pdo_t *ec_pdo_mapping_add_pdo(ec_pdo_mapping_t *, uint16_t,
+        ec_direction_t);
 int ec_pdo_mapping_add_pdo_copy(ec_pdo_mapping_t *, const ec_pdo_t *);
-int ec_pdo_mapping_add_pdo_info(ec_pdo_mapping_t *, const ec_pdo_info_t *,
-        const ec_slave_config_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);
 
--- a/master/slave_config.c	Thu Feb 28 14:18:37 2008 +0000
+++ b/master/slave_config.c	Thu Feb 28 14:29:50 2008 +0000
@@ -431,6 +431,58 @@
         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(
+        const ec_slave_config_t *sc,
+        ec_pdo_t *pdo
+        )
+{
+    const ec_sync_t *sync;
+    const ec_pdo_t *default_pdo;
+
+    pdo->default_config = 1;
+
+    if (!sc->slave) {
+        EC_WARN("Failed to load default Pdo configuration for %u:%u:"
+                " Slave not found.\n", sc->alias, sc->position);
+        return;
+    }
+
+    if (!(sync = ec_slave_get_pdo_sync(sc->slave, pdo->dir))) {
+        EC_WARN("Slave %u does not provide a default Pdo"
+                " configuration!\n", sc->slave->ring_position);
+        return;
+    }
+
+    list_for_each_entry(default_pdo, &sync->mapping.pdos, list) {
+        if (default_pdo->index != pdo->index)
+            continue;
+
+        if (sc->master->debug_level)
+            EC_DBG("  Found Pdo name \"%s\".\n",
+                    default_pdo->name);
+
+        // try to take Pdo name from mapped one
+        ec_pdo_set_name(pdo, default_pdo->name);
+
+        // copy entries (= default Pdo configuration)
+        if (ec_pdo_copy_entries(pdo, default_pdo))
+            return;
+
+        if (sc->master->debug_level) {
+            const ec_pdo_entry_t *entry;
+            list_for_each_entry(entry, &pdo->entries, list) {
+                EC_DBG("    Entry 0x%04X:%u.\n",
+                        entry->index, entry->subindex);
+            }
+        }
     }
 }
 
@@ -438,16 +490,89 @@
  *  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];
+    ec_pdo_t *pdo;
+    
+    if (pm->default_mapping) {
+        pm->default_mapping = 0;
+        ec_pdo_mapping_clear_pdos(pm);
+    }
+
+    if (!(pdo = ec_pdo_mapping_add_pdo(pm, index, dir)))
+        return -1;
+
+    ec_slave_config_load_default_pdo_config(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,
+        uint8_t entry_bit_length)
+{
+    ec_direction_t dir;
+    ec_pdo_t *pdo;
+    
+    for (dir = EC_DIR_OUTPUT; dir <= EC_DIR_INPUT; dir++)
+        if ((pdo = ec_pdo_mapping_find_pdo(&sc->mapping[dir], pdo_index)))
+            break;
+
+    if (pdo->default_config) {
+        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_entries,
         const ec_pdo_info_t pdo_infos[])
 {
     unsigned int i;
-
-    for (i = 0; i < n_entries; i++)
-        if (ec_pdo_mapping_add_pdo_info(&sc->mapping[pdo_infos[i].dir],
-                    &pdo_infos[i], sc))
+    const ec_pdo_info_t *pi;
+    ec_pdo_mapping_t *pm;
+    ec_pdo_t *pdo;
+    const ec_pdo_entry_info_t *ei;
+
+    for (i = 0; i < n_entries; i++) {
+        pi = &pdo_infos[i];
+        pm = &sc->mapping[pi->dir];
+
+        if (pm->default_mapping) {
+            pm->default_mapping = 0;
+            ec_pdo_mapping_clear_pdos(pm);
+        }
+
+        if (sc->master->debug_level)
+            EC_INFO("Adding Pdo 0x%04X to mapping.\n", pi->index);
+
+        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");
+
+            for (i = 0; i < pi->n_entries; i++) {
+                ei = &pi->entries[i];
+                if (!ec_pdo_add_entry(pdo, ei->index, ei->subindex,
+                            ei->bit_length))
+                    return -1;
+            }
+        } else { // use default Pdo configuration
+            if (sc->master->debug_level)
+                EC_DBG("  Using default Pdo configuration.\n");
+            ec_slave_config_load_default_pdo_config(sc, pdo);
+        }
+    }
+
     return 0;
 }
 
@@ -526,6 +651,8 @@
 
 /** \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_reg_pdo_entry);
 EXPORT_SYMBOL(ecrt_slave_config_sdo8);
--- a/master/slave_config.h	Thu Feb 28 14:18:37 2008 +0000
+++ b/master/slave_config.h	Thu Feb 28 14:29:50 2008 +0000
@@ -83,13 +83,12 @@
         uint16_t, uint32_t, uint32_t);
 void ec_slave_config_destroy(ec_slave_config_t *);
 
-int ec_slave_config_reg_pdo_entry(ec_slave_config_t *, ec_domain_t *,
-        uint16_t, uint8_t);
-
 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 *,
+        ec_pdo_t *);
 
 /*****************************************************************************/