Major Pdo configuration change: Read mapping of unknown Pdos during
authorFlorian Pose <fp@igh-essen.com>
Thu, 31 Jul 2008 16:13:29 +0000
changeset 1174 235f34ca50e2
parent 1173 2ec9651a6c89
child 1175 4684e0206eb9
Major Pdo configuration change: Read mapping of unknown Pdos during
configuration.
TODO
documentation/graphs/Makefile
documentation/graphs/fsm_coe_map.dot
documentation/graphs/fsm_pdo_assign.dot
documentation/graphs/fsm_pdo_conf.dot
documentation/graphs/fsm_pdo_entry_conf.dot
documentation/graphs/fsm_pdo_entry_read.dot
documentation/graphs/fsm_pdo_mapping.dot
documentation/graphs/fsm_pdo_read.dot
documentation/graphs/fsm_slave_conf.dot
master/Kbuild.in
master/Makefile.am
master/fsm_coe_map.c
master/fsm_coe_map.h
master/fsm_master.c
master/fsm_master.h
master/fsm_pdo.c
master/fsm_pdo.h
master/fsm_pdo_assign.c
master/fsm_pdo_assign.h
master/fsm_pdo_entry.c
master/fsm_pdo_entry.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.c
master/fsm_slave_scan.h
--- a/TODO	Thu Jul 31 09:30:38 2008 +0000
+++ b/TODO	Thu Jul 31 16:13:29 2008 +0000
@@ -8,12 +8,14 @@
 
 Version 1.4.0:
 
-* Read Pdo mapping for unknown Pdos before configuring them.
 * Attach Pdo names from SII or Coe dictioary to Pdos read via CoE.
 * Update documentation.
-* Get original driver for r8169.
 * Race in jiffies frame timeout?
-* Error at no sync manager for configuration.
+* Remove ec_sync_t::assign_source?
+* Repair rcethercat status.
+* Debug output for all configuration functions of the application interface.
+* Output warning, if there is no sync manager for a configuration.
+* Abort code messages in userspace.
 
 Future issues:
 
@@ -37,12 +39,12 @@
     - Add a -n (numeric) switch.
 	- Check for unwanted options.
 * Segmented Sdo downloads.
+* Get original driver for r8169.
 
 Smaller issues:
 
 * Stop master thread at ecrt_master_request() to get rid of allow_* flags?
 * Evaluate SII Size field (0x003E) to determine maximum SII memory size.
-* Unite fsm_pdo_mapping, fsm_pdo_config and fsm_coe_map.
 * Clear sync managers in INIT.
 * Read out CRC counters.
 * Configure slave ports to automatically open on link detection.
--- a/documentation/graphs/Makefile	Thu Jul 31 09:30:38 2008 +0000
+++ b/documentation/graphs/Makefile	Thu Jul 31 16:13:29 2008 +0000
@@ -5,10 +5,11 @@
 #-----------------------------------------------------------------------------
 
 GRAPHS := \
-	fsm_coe_map \
 	fsm_master \
-	fsm_pdo_assign \
-	fsm_pdo_mapping \
+	fsm_pdo_conf \
+	fsm_pdo_read \
+	fsm_pdo_entry_conf \
+	fsm_pdo_entry_read \
 	fsm_slave_conf \
 	fsm_slave_scan
 
--- a/documentation/graphs/fsm_coe_map.dot	Thu Jul 31 09:30:38 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-
-/* $Id$ */
-
-digraph readpdomapping {
-    size="7,9"
-    center=1
-	ratio=fill
-
-    next_sync [shape=point,label=""]
-    next_pdo [shape=point,label=""]
-    next_pdo_entry [shape=point,label=""]
-
-    start -> next_sync [label="first SM"]
-
-    next_sync -> pdo_count [weight=5]
-    next_sync -> end
-
-    pdo_count -> next_pdo [weight=5]
-
-    next_pdo -> pdo [weight=5]
-    next_pdo -> next_sync
-
-    pdo -> pdo_entry_count [weight=5]
-
-    pdo_entry_count -> next_pdo_entry [weight=10]
-
-    next_pdo_entry -> pdo_entry [weight=5]
-    next_pdo_entry -> next_pdo
-
-    pdo_entry -> next_pdo_entry
-
-    end
-}
--- a/documentation/graphs/fsm_pdo_assign.dot	Thu Jul 31 09:30:38 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-
-/* $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
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/documentation/graphs/fsm_pdo_conf.dot	Thu Jul 31 16:13:29 2008 +0000
@@ -0,0 +1,54 @@
+
+/* $Id$ */
+
+digraph pdo_conf {
+    size="7,9"
+    center=1
+	ratio=fill
+
+    start [fontname="Helvetica"]
+    start -> action_next_sync [fontname="Helvetica",label="First SM",weight=10]
+    start -> end [fontname="Helvetica",label="No config"]
+
+    action_next_sync [shape=point,label=""]
+    action_next_sync -> action_check_assignment [fontname="Helvetica",label="No Pdos"]
+    action_next_sync -> action_pdo_mapping [fontname="Helvetica",label="First Pdo",weight=10]
+    action_next_sync -> end [fontname="Helvetica",label="No more SMs"]
+
+    action_pdo_mapping [shape=point,label=""]
+    action_pdo_mapping -> read_mapping [fontname="Helvetica",label="Unknown"]
+    action_pdo_mapping -> action_check_mapping [weight=10]
+
+    read_mapping [fontname="Helvetica"]
+    read_mapping -> action_check_mapping
+
+    action_check_mapping [shape=point,label=""]
+    action_check_mapping -> action_next_pdo_mapping
+    action_check_mapping -> mapping [weight=10]
+
+    mapping [fontname="Helvetica"]
+    mapping -> action_next_pdo_mapping [weight=10]
+
+    action_next_pdo_mapping [shape=point,label=""]
+    action_next_pdo_mapping -> action_check_assignment [weight=10]
+    action_next_pdo_mapping -> action_pdo_mapping
+    [fontname="Helvetica",label="Next Pdo"]
+
+    action_check_assignment [shape=point,label=""]
+    action_check_assignment -> action_next_sync [fontname="Helvetica",label="Assign ok"]
+    action_check_assignment -> zero_pdo_count [weight=10]
+
+    zero_pdo_count [fontname="Helvetica"]
+    zero_pdo_count -> action_next_sync [fontname="Helvetica",label="No Pdos"]
+    zero_pdo_count -> action_assign_pdo [fontname="Helvetica",label="First Pdo", weight=10]
+
+    action_assign_pdo [shape=point,label=""]
+    action_assign_pdo -> assign_pdo [weight=10]
+
+    assign_pdo [fontname="Helvetica"]
+    assign_pdo -> set_pdo_count [fontname="Helvetica",label="No more Pdos", weight=10]
+    assign_pdo -> action_assign_pdo [fontname="Helvetica",label="Next Pdo"]
+
+    set_pdo_count [fontname="Helvetica"]
+    set_pdo_count -> action_next_sync
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/documentation/graphs/fsm_pdo_entry_conf.dot	Thu Jul 31 16:13:29 2008 +0000
@@ -0,0 +1,28 @@
+
+/* $Id$ */
+
+digraph pdo_entry_conf {
+    size="7,9"
+    center=1
+	ratio=fill
+
+	start [fontname="Helvetica"]
+    start -> zero_entry_count [weight=10]
+
+	zero_entry_count [fontname="Helvetica"]
+    zero_entry_count -> end [fontname="Helvetica",label="No Entries"]
+    zero_entry_count -> action_map [fontname="Helvetica",label="Add first entry", weight=10]
+
+    action_map [shape=point,label=""]
+	action_map -> map_entry [weight=10]
+
+	map_entry [fontname="Helvetica"]
+    map_entry -> action_map [fontname="Helvetica",label="Next entry"]
+    map_entry -> set_entry_count [fontname="Helvetica",label="No more Entries", weight=10]
+
+	set_entry_count [fontname="Helvetica"]
+    set_entry_count -> end [weight=10]
+
+	end [fontname="Helvetica"]
+	end
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/documentation/graphs/fsm_pdo_entry_read.dot	Thu Jul 31 16:13:29 2008 +0000
@@ -0,0 +1,23 @@
+
+/* $Id$ */
+
+digraph pdo_entry_read {
+    size="7,9"
+    center=1
+	ratio=fill
+
+	start [fontname="Helvetica"]
+    start -> count [weight=5]
+
+	count [fontname="Helvetica"]
+	count -> action_next [weight=5]
+
+    action_next [shape=point,label=""]
+    action_next -> pdo_entry [fontname="Helvetica", label="Next entry", weight=5]
+	action_next -> end [fontname="Helvetica", label="No more entries"]
+
+	pdo_entry [fontname="Helvetica"]
+    pdo_entry -> action_next
+
+    end [fontname="Helvetica"]
+}
--- a/documentation/graphs/fsm_pdo_mapping.dot	Thu Jul 31 09:30:38 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
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/documentation/graphs/fsm_pdo_read.dot	Thu Jul 31 16:13:29 2008 +0000
@@ -0,0 +1,30 @@
+
+/* $Id$ */
+
+digraph pdo_read {
+    size="7,9"
+    center=1
+	ratio=fill
+
+	start [fontname="Helvetica"]
+    start -> action_next_sync [fontname="Helvetica", label="First SM", weight=5]
+
+    action_next_sync [shape=point,label=""]
+    action_next_sync -> pdo_count [weight=5]
+    action_next_sync -> end
+
+	pdo_count [fontname="Helvetica"]
+    pdo_count -> action_next_pdo [weight=5]
+
+    action_next_pdo [shape=point,label=""]
+    action_next_pdo -> pdo [fontname="Helvetica", label="Next Pdo", weight=5]
+	action_next_pdo -> action_next_sync [fontname="Helvetica", label="No more Pdos"]
+
+	pdo [fontname="Helvetica"]
+    pdo -> pdo_entries [weight=5]
+
+	pdo_entries [fontname="Helvetica"]
+    pdo_entries -> action_next_pdo
+
+	end [fontname="Helvetica"]
+}
--- a/documentation/graphs/fsm_slave_conf.dot	Thu Jul 31 09:30:38 2008 +0000
+++ b/documentation/graphs/fsm_slave_conf.dot	Thu Jul 31 16:13:29 2008 +0000
@@ -53,17 +53,12 @@
     pdo_sync [fontname="Helvetica"]
     //pdo_sync -> pdo_sync
     //pdo_sync -> error
-    pdo_sync -> pdo_mapping [weight=10]
+    pdo_sync -> pdo_conf [weight=10]
 
-    pdo_mapping [fontname="Helvetica"]
-    //pdo_mapping -> pdo_mapping
-    //pdo_mapping -> error
-    pdo_mapping -> pdo_assign [weight=10]
-
-    pdo_assign [fontname="Helvetica"]
-    //pdo_assign -> pdo_assign
-    //pdo_assign -> error
-    pdo_assign -> enter_fmmu [weight=10]
+    pdo_conf [fontname="Helvetica"]
+    //pdo_conf -> pdo_conf
+    //pdo_conf -> error
+    pdo_conf -> enter_fmmu [weight=10]
 
     enter_fmmu [shape=point,label=""]
     enter_fmmu -> enter_safeop [fontname="Helvetica",label="No FMMUs\nto configure"]
--- a/master/Kbuild.in	Thu Jul 31 09:30:38 2008 +0000
+++ b/master/Kbuild.in	Thu Jul 31 16:13:29 2008 +0000
@@ -43,10 +43,9 @@
 	fmmu_config.o \
 	fsm_change.o \
 	fsm_coe.o \
-	fsm_coe_map.o \
 	fsm_master.o \
-	fsm_pdo_assign.o \
-	fsm_pdo_mapping.o \
+	fsm_pdo.o \
+	fsm_pdo_entry.o \
 	fsm_sii.o \
 	fsm_slave_config.o \
 	fsm_slave_scan.o \
--- a/master/Makefile.am	Thu Jul 31 09:30:38 2008 +0000
+++ b/master/Makefile.am	Thu Jul 31 16:13:29 2008 +0000
@@ -43,10 +43,9 @@
 	fmmu_config.c fmmu_config.h \
 	fsm_change.c fsm_change.h \
 	fsm_coe.c fsm_coe.h \
-	fsm_coe_map.c fsm_coe_map.h \
 	fsm_master.c fsm_master.h \
-	fsm_pdo_assign.c fsm_pdo_assign.h \
-	fsm_pdo_mapping.c fsm_pdo_mapping.h \
+	fsm_pdo.c fsm_pdo.h \
+	fsm_pdo_entry.c fsm_pdo_entry.h \
 	fsm_sii.c fsm_sii.h \
 	fsm_slave_config.c fsm_slave_config.h \
 	fsm_slave_scan.c fsm_slave_scan.h \
--- a/master/fsm_coe_map.c	Thu Jul 31 09:30:38 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,460 +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 information state machines.
-*/
-
-/*****************************************************************************/
-
-#include "globals.h"
-#include "master.h"
-#include "mailbox.h"
-#include "sdo_request.h"
-#include "fsm_coe_map.h"
-
-/*****************************************************************************/
-
-void ec_fsm_coe_map_state_start(ec_fsm_coe_map_t *);
-void ec_fsm_coe_map_state_pdo_count(ec_fsm_coe_map_t *);
-void ec_fsm_coe_map_state_pdo(ec_fsm_coe_map_t *);
-void ec_fsm_coe_map_state_pdo_entry_count(ec_fsm_coe_map_t *);
-void ec_fsm_coe_map_state_pdo_entry(ec_fsm_coe_map_t *);
-
-void ec_fsm_coe_map_state_end(ec_fsm_coe_map_t *);
-void ec_fsm_coe_map_state_error(ec_fsm_coe_map_t *);
-
-void ec_fsm_coe_map_action_next_sync(ec_fsm_coe_map_t *);
-void ec_fsm_coe_map_action_next_pdo(ec_fsm_coe_map_t *);
-void ec_fsm_coe_map_action_next_pdo_entry(ec_fsm_coe_map_t *);
-
-/*****************************************************************************/
-
-/**
-   Constructor.
-*/
-
-void ec_fsm_coe_map_init(
-        ec_fsm_coe_map_t *fsm, /**< finite state machine */
-        ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */
-        )
-{
-    fsm->fsm_coe = fsm_coe;
-    fsm->state = NULL;
-    ec_sdo_request_init(&fsm->request);
-    ec_pdo_list_init(&fsm->pdos);
-}
-
-/*****************************************************************************/
-
-/**
-   Destructor.
-*/
-
-void ec_fsm_coe_map_clear(ec_fsm_coe_map_t *fsm /**< finite state machine */)
-{
-    ec_sdo_request_clear(&fsm->request);
-    ec_pdo_list_clear(&fsm->pdos);
-}
-
-/*****************************************************************************/
-
-/**
-   Starts to upload an Sdo from a slave.
-*/
-
-void ec_fsm_coe_map_start(
-        ec_fsm_coe_map_t *fsm, /**< finite state machine */
-        ec_slave_t *slave /**< EtherCAT slave */
-        )
-{
-    fsm->slave = slave;
-    fsm->state = ec_fsm_coe_map_state_start;
-}
-
-/*****************************************************************************/
-
-/**
-   Executes the current state of the state machine.
-   \return false, if state machine has terminated
-*/
-
-int ec_fsm_coe_map_exec(ec_fsm_coe_map_t *fsm /**< finite state machine */)
-{
-    fsm->state(fsm);
-
-    return fsm->state != ec_fsm_coe_map_state_end
-        && fsm->state != ec_fsm_coe_map_state_error;
-}
-
-/*****************************************************************************/
-
-/**
-   Returns, if the state machine terminated with success.
-   \return non-zero if successful.
-*/
-
-int ec_fsm_coe_map_success(ec_fsm_coe_map_t *fsm /**< Finite state machine */)
-{
-    return fsm->state == ec_fsm_coe_map_state_end;
-}
-
-/******************************************************************************
- *  state functions
- *****************************************************************************/
-
-/** Start reading Pdo assignment.
- */
-void ec_fsm_coe_map_state_start(
-        ec_fsm_coe_map_t *fsm /**< finite state machine */
-        )
-{
-    // read Pdo assignment for first sync manager not reserved for mailbox
-    fsm->sync_index = 1; // next is 2
-    ec_fsm_coe_map_action_next_sync(fsm);
-}
-
-/*****************************************************************************/
-
-/** Read Pdo assignment of next sync manager.
- */
-void ec_fsm_coe_map_action_next_sync(
-        ec_fsm_coe_map_t *fsm /**< Finite state machine */
-        )
-{
-    ec_slave_t *slave = fsm->slave;
-
-    fsm->sync_index++;
-
-    for (; fsm->sync_index < EC_MAX_SYNC_MANAGERS; fsm->sync_index++) {
-        if (!(fsm->sync = ec_slave_get_sync(slave, fsm->sync_index)))
-            continue;
-
-        fsm->sync_sdo_index = 0x1C10 + fsm->sync_index;
-
-        if (slave->master->debug_level)
-            EC_DBG("Reading Pdo assignment of SM%u of slave %u.\n",
-                    fsm->sync_index, slave->ring_position);
-
-        ec_pdo_list_clear_pdos(&fsm->pdos);
-
-        ec_sdo_request_address(&fsm->request, fsm->sync_sdo_index, 0);
-        ecrt_sdo_request_read(&fsm->request);
-        fsm->state = ec_fsm_coe_map_state_pdo_count;
-        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
-        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
-        return;
-    }
-
-    if (slave->master->debug_level)
-        EC_DBG("Reading of Pdo assignment finished for slave %u.\n",
-                slave->ring_position);
-
-    fsm->state = ec_fsm_coe_map_state_end;
-}
-
-/*****************************************************************************/
-
-/**
- * Count assigned Pdos.
- */
-
-void ec_fsm_coe_map_state_pdo_count(
-        ec_fsm_coe_map_t *fsm /**< finite state machine */
-        )
-{
-    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
-
-    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        EC_ERR("Failed to read number of assigned Pdos from slave %u.\n",
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_coe_map_state_error;
-        return;
-    }
-
-    if (fsm->request.data_size != sizeof(uint8_t)) {
-        EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X "
-                "from slave %u.\n", fsm->request.data_size,
-                fsm->request.index, fsm->request.subindex,
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_coe_map_state_error;
-        return;
-    }
-    fsm->sync_subindices = EC_READ_U8(fsm->request.data);
-
-    if (fsm->slave->master->debug_level)
-        EC_DBG("%u Pdos assigned.\n", fsm->sync_subindices);
-
-    // read first Pdo
-    fsm->sync_subindex = 1;
-    ec_fsm_coe_map_action_next_pdo(fsm);
-}
-
-/*****************************************************************************/
-
-/**
- * Read next Pdo.
- */
-
-void ec_fsm_coe_map_action_next_pdo(
-        ec_fsm_coe_map_t *fsm /**< finite state machine */
-        )
-{
-    if (fsm->sync_subindex <= fsm->sync_subindices) {
-        ec_sdo_request_address(&fsm->request, fsm->sync_sdo_index,
-                fsm->sync_subindex);
-        ecrt_sdo_request_read(&fsm->request);
-        fsm->state = ec_fsm_coe_map_state_pdo;
-        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
-        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
-        return;
-    }
-
-    // finished reading Pdo assignment/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 sync manager
-    ec_fsm_coe_map_action_next_sync(fsm);
-}
-
-/*****************************************************************************/
-
-/**
- * Fetch Pdo information.
- */
-
-void ec_fsm_coe_map_state_pdo(
-        ec_fsm_coe_map_t *fsm /**< finite state machine */
-        )
-{
-    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
-
-    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        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;
-    }
-
-    if (fsm->request.data_size != sizeof(uint16_t)) {
-        EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X "
-                "from slave %u.\n", fsm->request.data_size,
-                fsm->request.index, fsm->request.subindex,
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_coe_map_state_error;
-        return;
-    }
-
-    if (!(fsm->pdo = (ec_pdo_t *)
-                kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
-        EC_ERR("Failed to allocate Pdo.\n");
-        fsm->state = ec_fsm_coe_map_state_error;
-        return;
-    }
-
-    ec_pdo_init(fsm->pdo);
-    fsm->pdo->index = EC_READ_U16(fsm->request.data);
-    fsm->pdo->sync_index = fsm->sync_index;
-
-    if (fsm->slave->master->debug_level)
-        EC_DBG("Pdo 0x%04X.\n", fsm->pdo->index);
-
-    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);
-    fsm->state = ec_fsm_coe_map_state_pdo_entry_count;
-    ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
-    ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
-}
-
-/*****************************************************************************/
-
-/**
- * Read number of mapped Pdo entries.
- */
-
-void ec_fsm_coe_map_state_pdo_entry_count(
-        ec_fsm_coe_map_t *fsm /**< finite state machine */
-        )
-{
-    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
-
-    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        EC_ERR("Failed to read number of mapped Pdo entries from slave %u.\n",
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_coe_map_state_error;
-        return;
-    }
-
-    if (fsm->request.data_size != sizeof(uint8_t)) {
-        EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X "
-                "from slave %u.\n", fsm->request.data_size,
-                fsm->request.index, fsm->request.subindex,
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_coe_map_state_error;
-        return;
-    }
-    fsm->pdo_subindices = EC_READ_U8(fsm->request.data);
-
-    if (fsm->slave->master->debug_level)
-        EC_DBG("%u Pdo entries mapped.\n", fsm->pdo_subindices);
-
-    // read first Pdo entry
-    fsm->pdo_subindex = 1;
-    ec_fsm_coe_map_action_next_pdo_entry(fsm);
-}
-
-/*****************************************************************************/
-
-/**
- * Read next Pdo entry.
- */
-
-void ec_fsm_coe_map_action_next_pdo_entry(
-        ec_fsm_coe_map_t *fsm /**< finite state machine */
-        )
-{
-    if (fsm->pdo_subindex <= fsm->pdo_subindices) {
-        ec_sdo_request_address(&fsm->request, fsm->pdo->index, fsm->pdo_subindex);
-        ecrt_sdo_request_read(&fsm->request);
-        fsm->state = ec_fsm_coe_map_state_pdo_entry;
-        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
-        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
-        return;
-    }
-
-    // next Pdo
-    fsm->sync_subindex++;
-    ec_fsm_coe_map_action_next_pdo(fsm);
-}
-
-/*****************************************************************************/
-
-/**
- * Read Pdo entry information.
- */
-
-void ec_fsm_coe_map_state_pdo_entry(
-        ec_fsm_coe_map_t *fsm /**< finite state machine */
-        )
-{
-    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
-
-    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        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;
-    }
-
-    if (fsm->request.data_size != sizeof(uint32_t)) {
-        EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X "
-                "from slave %u.\n", fsm->request.data_size,
-                fsm->request.index, fsm->request.subindex,
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_coe_map_state_error;
-    } else {
-        uint32_t pdo_entry_info;
-        ec_pdo_entry_t *pdo_entry;
-
-        pdo_entry_info = EC_READ_U32(fsm->request.data);
-
-        if (!(pdo_entry = (ec_pdo_entry_t *)
-                    kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
-            EC_ERR("Failed to allocate Pdo entry.\n");
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
-
-        ec_pdo_entry_init(pdo_entry);
-        pdo_entry->index = pdo_entry_info >> 16;
-        pdo_entry->subindex = (pdo_entry_info >> 8) & 0xFF;
-        pdo_entry->bit_length = pdo_entry_info & 0xFF;
-
-        if (!pdo_entry->index && !pdo_entry->subindex) {
-            if (ec_pdo_entry_set_name(pdo_entry, "Gap")) {
-                ec_pdo_entry_clear(pdo_entry);
-                kfree(pdo_entry);
-                fsm->state = ec_fsm_coe_map_state_error;
-                return;
-            }
-        }
-
-        if (fsm->slave->master->debug_level) {
-            EC_DBG("Pdo entry 0x%04X:%02X, %u bit, \"%s\".\n",
-                    pdo_entry->index, pdo_entry->subindex,
-                    pdo_entry->bit_length,
-                    pdo_entry->name ? pdo_entry->name : "???");
-        }
-
-        // next Pdo entry
-        list_add_tail(&pdo_entry->list, &fsm->pdo->entries);
-        fsm->pdo_subindex++;
-        ec_fsm_coe_map_action_next_pdo_entry(fsm);
-    }
-}
-
-/*****************************************************************************/
-
-/**
-   State: ERROR.
-*/
-
-void ec_fsm_coe_map_state_error(
-        ec_fsm_coe_map_t *fsm /**< finite state machine */
-        )
-{
-}
-
-/*****************************************************************************/
-
-/**
-   State: END.
-*/
-
-void ec_fsm_coe_map_state_end(
-        ec_fsm_coe_map_t *fsm /**< finite state machine */
-        )
-{
-}
-
-/*****************************************************************************/
--- a/master/fsm_coe_map.h	Thu Jul 31 09:30:38 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +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 CoE mapping state machines.
-*/
-
-/*****************************************************************************/
-
-#ifndef __EC_FSM_COE_MAP_H__
-#define __EC_FSM_COE_MAP_H__
-
-#include "globals.h"
-#include "datagram.h"
-#include "slave.h"
-#include "fsm_coe.h"
-
-/*****************************************************************************/
-
-typedef struct ec_fsm_coe_map ec_fsm_coe_map_t; /**< \see ec_fsm_coe_map */
-
-/**
- * \todo doc
- */
-struct ec_fsm_coe_map
-{
-    void (*state)(ec_fsm_coe_map_t *); /**< CoE mapping state function */
-    ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use */
-
-    ec_slave_t *slave; /**< EtherCAT slave */
-    ec_sdo_request_t request; /**< Sdo request */
-
-    uint8_t sync_index; /**< Index of the current sync manager. */
-    ec_sync_t *sync; /**< Pdo sync manager. */
-    uint16_t sync_sdo_index; /**< Index of the mapping Sdo. */
-    uint8_t sync_subindices; /**< number of mapped Pdos */
-    uint16_t sync_subindex; /**< current subindex in mapping 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. */
-};
-
-/*****************************************************************************/
-
-void ec_fsm_coe_map_init(ec_fsm_coe_map_t *, ec_fsm_coe_t *);
-void ec_fsm_coe_map_clear(ec_fsm_coe_map_t *);
-
-void ec_fsm_coe_map_start(ec_fsm_coe_map_t *, ec_slave_t *);
-
-int ec_fsm_coe_map_exec(ec_fsm_coe_map_t *);
-int ec_fsm_coe_map_success(ec_fsm_coe_map_t *);
-
-/*****************************************************************************/
-
-#endif
--- a/master/fsm_master.c	Thu Jul 31 09:30:38 2008 +0000
+++ b/master/fsm_master.c	Thu Jul 31 16:13:29 2008 +0000
@@ -79,13 +79,14 @@
     fsm->slave_states = EC_SLAVE_STATE_UNKNOWN;
 
     // init sub-state-machines
-    ec_fsm_slave_config_init(&fsm->fsm_slave_config, fsm->datagram);
+    ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram);
+    ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
+    ec_fsm_change_init(&fsm->fsm_change, fsm->datagram);
+    ec_fsm_slave_config_init(&fsm->fsm_slave_config, fsm->datagram,
+            &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_pdo);
     ec_fsm_slave_scan_init(&fsm->fsm_slave_scan, fsm->datagram,
-            &fsm->fsm_slave_config, &fsm->fsm_coe_map);
+            &fsm->fsm_slave_config, &fsm->fsm_pdo);
     ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
-    ec_fsm_change_init(&fsm->fsm_change, fsm->datagram);
-    ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram);
-    ec_fsm_coe_map_init(&fsm->fsm_coe_map, &fsm->fsm_coe);
 }
 
 /*****************************************************************************/
@@ -97,12 +98,12 @@
         )
 {
     // clear sub-state machines
+    ec_fsm_coe_clear(&fsm->fsm_coe);
+    ec_fsm_pdo_clear(&fsm->fsm_pdo);
+    ec_fsm_change_clear(&fsm->fsm_change);
     ec_fsm_slave_config_clear(&fsm->fsm_slave_config);
     ec_fsm_slave_scan_clear(&fsm->fsm_slave_scan);
     ec_fsm_sii_clear(&fsm->fsm_sii);
-    ec_fsm_change_clear(&fsm->fsm_change);
-    ec_fsm_coe_clear(&fsm->fsm_coe);
-    ec_fsm_coe_map_clear(&fsm->fsm_coe_map);
 }
 
 /*****************************************************************************/
--- a/master/fsm_master.h	Thu Jul 31 09:30:38 2008 +0000
+++ b/master/fsm_master.h	Thu Jul 31 16:13:29 2008 +0000
@@ -48,7 +48,7 @@
 #include "sdo_request.h"
 #include "fsm_slave_config.h"
 #include "fsm_slave_scan.h"
-#include "fsm_coe_map.h"
+#include "fsm_pdo.h"
 
 /*****************************************************************************/
 
@@ -95,12 +95,12 @@
     off_t sii_index; /**< index to SII write request data */
     ec_sdo_request_t *sdo_request; /**< Sdo request to process. */
 
+    ec_fsm_coe_t fsm_coe; /**< CoE state machine */
+    ec_fsm_pdo_t fsm_pdo; /**< Pdo configuration state machine. */
+    ec_fsm_change_t fsm_change; /**< State change state machine */
     ec_fsm_slave_config_t fsm_slave_config; /**< slave state machine */
     ec_fsm_slave_scan_t fsm_slave_scan; /**< slave state machine */
     ec_fsm_sii_t fsm_sii; /**< SII state machine */
-    ec_fsm_change_t fsm_change; /**< State change state machine */
-    ec_fsm_coe_t fsm_coe; /**< CoE state machine */
-    ec_fsm_coe_map_t fsm_coe_map; /**< CoE mapping state machine */
 };
 
 /*****************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/fsm_pdo.c	Thu Jul 31 16:13:29 2008 +0000
@@ -0,0 +1,762 @@
+/******************************************************************************
+ *
+ *  $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.h"
+
+/*****************************************************************************/
+
+void ec_fsm_pdo_read_state_start(ec_fsm_pdo_t *);
+void ec_fsm_pdo_read_state_pdo_count(ec_fsm_pdo_t *);
+void ec_fsm_pdo_read_state_pdo(ec_fsm_pdo_t *);
+void ec_fsm_pdo_read_state_pdo_entries(ec_fsm_pdo_t *);
+
+void ec_fsm_pdo_read_action_next_sync(ec_fsm_pdo_t *);
+void ec_fsm_pdo_read_action_next_pdo(ec_fsm_pdo_t *);
+
+void ec_fsm_pdo_conf_state_start(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_state_read_mapping(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_state_mapping(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_state_zero_pdo_count(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_state_assign_pdo(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_state_set_pdo_count(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_state_entries(ec_fsm_pdo_t *);
+
+void ec_fsm_pdo_conf_action_next_sync(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_action_pdo_mapping(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_action_check_mapping(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_action_next_pdo_mapping(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_action_check_assignment(ec_fsm_pdo_t *);
+void ec_fsm_pdo_conf_action_assign_pdo(ec_fsm_pdo_t *);
+
+void ec_fsm_pdo_state_end(ec_fsm_pdo_t *);
+void ec_fsm_pdo_state_error(ec_fsm_pdo_t *);
+
+/*****************************************************************************/
+
+/** Constructor.
+ */
+void ec_fsm_pdo_init(
+        ec_fsm_pdo_t *fsm, /**< Pdo configuration state machine. */
+        ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */
+        )
+{
+    fsm->fsm_coe = fsm_coe;
+    ec_fsm_pdo_entry_init(&fsm->fsm_pdo_entry, fsm_coe);
+    ec_pdo_list_init(&fsm->pdos);
+    ec_sdo_request_init(&fsm->request);
+    ec_pdo_init(&fsm->slave_pdo);
+}
+
+/*****************************************************************************/
+
+/** Destructor.
+ */
+void ec_fsm_pdo_clear(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    ec_fsm_pdo_entry_clear(&fsm->fsm_pdo_entry);
+    ec_pdo_list_clear(&fsm->pdos);
+    ec_sdo_request_clear(&fsm->request);
+    ec_pdo_clear(&fsm->slave_pdo);
+}
+
+/*****************************************************************************/
+
+/** Start reading the Pdo configuration.
+ */
+void ec_fsm_pdo_start_reading(
+        ec_fsm_pdo_t *fsm, /**< Pdo configuration state machine. */
+        ec_slave_t *slave /**< slave to configure */
+        )
+{
+    fsm->slave = slave;
+    fsm->state = ec_fsm_pdo_read_state_start;
+}
+
+/*****************************************************************************/
+
+/** Start writing the Pdo configuration.
+ */
+void ec_fsm_pdo_start_configuration(
+        ec_fsm_pdo_t *fsm, /**< Pdo configuration state machine. */
+        ec_slave_t *slave /**< slave to configure */
+        )
+{
+    fsm->slave = slave;
+    fsm->state = ec_fsm_pdo_conf_state_start;
+}
+
+/*****************************************************************************/
+
+/** Get running state.
+ *
+ * \return false, if state machine has terminated
+ */
+int ec_fsm_pdo_running(
+        const ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    return fsm->state != ec_fsm_pdo_state_end
+        && fsm->state != ec_fsm_pdo_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_exec(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    fsm->state(fsm);
+    return ec_fsm_pdo_running(fsm);
+}
+
+/*****************************************************************************/
+
+/** Get execution result.
+ *
+ * \return true, if the state machine terminated gracefully
+ */
+int ec_fsm_pdo_success(
+        const ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    return fsm->state == ec_fsm_pdo_state_end;
+}
+
+/******************************************************************************
+ * Reading state funtions.
+ *****************************************************************************/
+
+/** Start reading Pdo assignment.
+ */
+void ec_fsm_pdo_read_state_start(
+        ec_fsm_pdo_t *fsm /**< finite state machine */
+        )
+{
+    // read Pdo assignment for first sync manager not reserved for mailbox
+    fsm->sync_index = 1; // next is 2
+    ec_fsm_pdo_read_action_next_sync(fsm);
+}
+
+/*****************************************************************************/
+
+/** Read Pdo assignment of next sync manager.
+ */
+void ec_fsm_pdo_read_action_next_sync(
+        ec_fsm_pdo_t *fsm /**< Finite state machine */
+        )
+{
+    ec_slave_t *slave = fsm->slave;
+
+    fsm->sync_index++;
+
+    for (; fsm->sync_index < EC_MAX_SYNC_MANAGERS; fsm->sync_index++) {
+        if (!(fsm->sync = ec_slave_get_sync(slave, fsm->sync_index)))
+            continue;
+
+        if (slave->master->debug_level)
+            EC_DBG("Reading Pdo assignment of SM%u.\n", fsm->sync_index);
+
+        ec_pdo_list_clear_pdos(&fsm->pdos);
+
+        ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, 0);
+        ecrt_sdo_request_read(&fsm->request);
+        fsm->state = ec_fsm_pdo_read_state_pdo_count;
+        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
+        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
+        return;
+    }
+
+    if (slave->master->debug_level)
+        EC_DBG("Reading of Pdo configuration finished.\n");
+
+    fsm->state = ec_fsm_pdo_state_end;
+}
+
+/*****************************************************************************/
+
+/** Count assigned Pdos.
+ */
+void ec_fsm_pdo_read_state_pdo_count(
+        ec_fsm_pdo_t *fsm /**< finite state machine */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_ERR("Failed to read number of assigned Pdos for SM%u.\n",
+                fsm->sync_index);
+        fsm->state = ec_fsm_pdo_state_error;
+        return;
+    }
+
+    if (fsm->request.data_size != sizeof(uint8_t)) {
+        EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X "
+                "from slave %u.\n", fsm->request.data_size,
+                fsm->request.index, fsm->request.subindex,
+                fsm->slave->ring_position);
+        fsm->state = ec_fsm_pdo_state_error;
+        return;
+    }
+    fsm->pdo_count = EC_READ_U8(fsm->request.data);
+
+    if (fsm->slave->master->debug_level)
+        EC_DBG("%u Pdos assigned.\n", fsm->pdo_count);
+
+    // read first Pdo
+    fsm->pdo_pos = 1;
+    ec_fsm_pdo_read_action_next_pdo(fsm);
+}
+
+/*****************************************************************************/
+
+/** Read next Pdo.
+ */
+void ec_fsm_pdo_read_action_next_pdo(
+        ec_fsm_pdo_t *fsm /**< finite state machine */
+        )
+{
+    if (fsm->pdo_pos <= fsm->pdo_count) {
+        ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index,
+                fsm->pdo_pos);
+        ecrt_sdo_request_read(&fsm->request);
+        fsm->state = ec_fsm_pdo_read_state_pdo;
+        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
+        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
+        return;
+    }
+
+    // finished reading Pdo configuration
+    
+    if (ec_pdo_list_copy(&fsm->sync->pdos, &fsm->pdos)) {
+        fsm->state = ec_fsm_pdo_state_error;
+        return;
+    }
+
+    fsm->sync->assign_source = EC_ASSIGN_COE;
+    ec_pdo_list_clear_pdos(&fsm->pdos);
+
+    // next sync manager
+    ec_fsm_pdo_read_action_next_sync(fsm);
+}
+
+/*****************************************************************************/
+
+/** Fetch Pdo information.
+ */
+void ec_fsm_pdo_read_state_pdo(
+        ec_fsm_pdo_t *fsm /**< finite state machine */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_ERR("Failed to read index of assigned Pdo %u from SM%u.\n",
+                fsm->pdo_pos, fsm->sync_index);
+        fsm->state = ec_fsm_pdo_state_error;
+        return;
+    }
+
+    if (fsm->request.data_size != sizeof(uint16_t)) {
+        EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X "
+                "from slave %u.\n", fsm->request.data_size,
+                fsm->request.index, fsm->request.subindex,
+                fsm->slave->ring_position);
+        fsm->state = ec_fsm_pdo_state_error;
+        return;
+    }
+
+    if (!(fsm->pdo = (ec_pdo_t *)
+                kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) {
+        EC_ERR("Failed to allocate Pdo.\n");
+        fsm->state = ec_fsm_pdo_state_error;
+        return;
+    }
+
+    ec_pdo_init(fsm->pdo);
+    fsm->pdo->index = EC_READ_U16(fsm->request.data);
+    fsm->pdo->sync_index = fsm->sync_index;
+
+    if (fsm->slave->master->debug_level)
+        EC_DBG("Pdo 0x%04X.\n", fsm->pdo->index);
+
+    list_add_tail(&fsm->pdo->list, &fsm->pdos.list);
+
+    fsm->state = ec_fsm_pdo_read_state_pdo_entries;
+    ec_fsm_pdo_entry_start_reading(&fsm->fsm_pdo_entry, fsm->slave, fsm->pdo);
+    fsm->state(fsm); // execute immediately
+}
+
+/*****************************************************************************/
+
+/** Fetch Pdo information.
+ */
+void ec_fsm_pdo_read_state_pdo_entries(
+        ec_fsm_pdo_t *fsm /**< finite state machine */
+        )
+{
+    if (ec_fsm_pdo_entry_exec(&fsm->fsm_pdo_entry))
+        return;
+
+    if (!ec_fsm_pdo_entry_success(&fsm->fsm_pdo_entry)) {
+        EC_ERR("Failed to read mapped Pdo entries for Pdo 0x%04X.\n",
+                fsm->pdo->index);
+        fsm->state = ec_fsm_pdo_state_error;
+        return;
+    }
+
+    // next Pdo
+    fsm->pdo_pos++;
+    ec_fsm_pdo_read_action_next_pdo(fsm);
+}
+
+/******************************************************************************
+ * Writing state functions.
+ *****************************************************************************/
+
+/** Start Pdo configuration.
+ */
+void ec_fsm_pdo_conf_state_start(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    if (!fsm->slave->config) {
+        fsm->state = ec_fsm_pdo_state_end;
+        return;
+    }
+
+    fsm->sync_index = 0xff; // next is zero
+    ec_fsm_pdo_conf_action_next_sync(fsm);
+}
+
+/*****************************************************************************/
+
+/** Assign next Pdo.
+ */
+ec_pdo_t *ec_fsm_pdo_conf_action_next_pdo(
+        const ec_fsm_pdo_t *fsm, /**< Pdo configuration 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);
+}
+
+/*****************************************************************************/
+
+/** Get the next sync manager for a pdo configuration.
+ */
+void ec_fsm_pdo_conf_action_next_sync(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    fsm->sync_index++;
+
+    for (; fsm->sync_index < EC_MAX_SYNC_MANAGERS; fsm->sync_index++) {
+        if (ec_pdo_list_copy(&fsm->pdos,
+                    &fsm->slave->config->sync_configs[fsm->sync_index].pdos)) {
+            fsm->state = ec_fsm_pdo_state_error;
+            return;
+        }
+        
+        if (!(fsm->sync = ec_slave_get_sync(fsm->slave, fsm->sync_index))) {
+            if (!list_empty(&fsm->pdos.list))
+                EC_WARN("Pdos configured for SM%u, but slave %u does not "
+                        "provide a sync manager configuration!\n",
+                        fsm->sync_index, fsm->slave->ring_position);
+            continue;
+        }
+
+        // get first configured Pdo
+        if (!(fsm->pdo = ec_fsm_pdo_conf_action_next_pdo(fsm, &fsm->pdos.list))) {
+            // no pdos configured
+            ec_fsm_pdo_conf_action_check_assignment(fsm);
+            return;
+        }
+
+        ec_fsm_pdo_conf_action_pdo_mapping(fsm);
+        return;
+    }
+
+    fsm->state = ec_fsm_pdo_state_end;
+}
+
+/*****************************************************************************/
+
+/**
+ */
+void ec_fsm_pdo_conf_action_pdo_mapping(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    const ec_pdo_t *assigned_pdo;
+
+    fsm->slave_pdo.index = fsm->pdo->index;
+
+    if ((assigned_pdo = ec_slave_find_pdo(fsm->slave, fsm->pdo->index))) {
+        ec_pdo_copy_entries(&fsm->slave_pdo, assigned_pdo);
+    } else { // configured Pdo is not assigned and thus unknown
+        ec_pdo_clear_entries(&fsm->slave_pdo);
+    }
+
+    if (list_empty(&fsm->slave_pdo.entries)) {
+
+        if (fsm->slave->master->debug_level)
+            EC_DBG("Reading mapping of Pdo 0x%04X.\n",
+                    fsm->pdo->index);
+            
+        // pdo mapping is unknown; start loading it
+        ec_fsm_pdo_entry_start_reading(&fsm->fsm_pdo_entry, fsm->slave,
+                &fsm->slave_pdo);
+        fsm->state = ec_fsm_pdo_conf_state_read_mapping;
+        fsm->state(fsm); // execute immediately
+        return;
+    }
+
+    // pdo mapping is known, check if it most be re-configured
+    ec_fsm_pdo_conf_action_check_mapping(fsm);
+}
+
+/*****************************************************************************/
+
+/**
+ */
+void ec_fsm_pdo_conf_state_read_mapping(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    if (ec_fsm_pdo_entry_exec(&fsm->fsm_pdo_entry))
+        return;
+
+    if (!ec_fsm_pdo_entry_success(&fsm->fsm_pdo_entry))
+        EC_WARN("Failed to read mapped Pdo entries for Pdo 0x%04X.\n",
+                fsm->pdo->index);
+
+    // check if the mapping must be re-configured
+    ec_fsm_pdo_conf_action_check_mapping(fsm);
+}
+
+/*****************************************************************************/
+
+/**
+ */
+void ec_fsm_pdo_conf_action_check_mapping(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    if (ec_pdo_equal_entries(fsm->pdo, &fsm->slave_pdo)) {
+        if (fsm->slave->master->debug_level)
+            EC_DBG("Mapping of Pdo 0x%04X is already configured correctly.\n",
+                    fsm->pdo->index);
+        ec_fsm_pdo_conf_action_next_pdo_mapping(fsm);
+        return;
+    }
+
+    if (fsm->slave->master->debug_level) {
+        // TODO display diff
+        EC_DBG("Changing mapping of Pdo 0x%04X.\n", fsm->pdo->index);
+    }
+
+    ec_fsm_pdo_entry_start_configuration(&fsm->fsm_pdo_entry, fsm->slave,
+            fsm->pdo);
+    fsm->state = ec_fsm_pdo_conf_state_mapping;
+    fsm->state(fsm); // execure immediately
+}
+
+/*****************************************************************************/
+
+/**
+ */
+void ec_fsm_pdo_conf_state_mapping(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    if (ec_fsm_pdo_entry_exec(&fsm->fsm_pdo_entry))
+        return;
+
+    if (!ec_fsm_pdo_entry_success(&fsm->fsm_pdo_entry))
+        EC_WARN("Failed to configure mapping of Pdo 0x%04X.\n",
+                fsm->pdo->index);
+
+    ec_fsm_pdo_conf_action_next_pdo_mapping(fsm);
+}
+
+/*****************************************************************************/
+
+/**
+ */
+void ec_fsm_pdo_conf_action_next_pdo_mapping(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    // get next configured Pdo
+    if (!(fsm->pdo = ec_fsm_pdo_conf_action_next_pdo(fsm, &fsm->pdo->list))) {
+        // no more configured pdos
+        ec_fsm_pdo_conf_action_check_assignment(fsm);
+        return;
+    }
+
+    ec_fsm_pdo_conf_action_pdo_mapping(fsm);
+}
+
+/*****************************************************************************/
+
+/**
+ */
+void ec_fsm_pdo_conf_action_check_assignment(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    // check if assignment has to be re-configured
+    if (ec_pdo_list_equal(&fsm->sync->pdos, &fsm->pdos)) {
+
+        if (fsm->slave->master->debug_level)
+            EC_DBG("Pdo assignment for SM%u is already configured "
+                    "correctly.\n", fsm->sync_index);
+
+        ec_fsm_pdo_conf_action_next_sync(fsm);
+        return;
+    }
+
+    if (fsm->slave->master->debug_level) {
+        EC_DBG("Pdo assignment of SM%u differs:\n", fsm->sync_index);
+        EC_DBG("Currently assigned Pdos: ");
+        ec_pdo_list_print(&fsm->sync->pdos);
+        printk("\n");
+        EC_DBG("Pdos to assign: ");
+        ec_pdo_list_print(&fsm->pdos);
+        printk("\n");
+    }
+
+    // Pdo assignment has to be changed. Does the slave support this?
+    if (!(fsm->slave->sii.mailbox_protocols & EC_MBOX_COE)
+            || (fsm->slave->sii.has_general
+                && !fsm->slave->sii.coe_details.enable_pdo_assign)) {
+        EC_WARN("Slave %u does not support assigning Pdos!\n",
+                fsm->slave->ring_position);
+        ec_fsm_pdo_conf_action_next_sync(fsm);
+        return;
+    }
+
+    if (ec_sdo_request_alloc(&fsm->request, 2)) {
+        fsm->state = ec_fsm_pdo_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 number of assigned Pdos to zero.\n");
+
+    fsm->state = ec_fsm_pdo_conf_state_zero_pdo_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 assigned Pdos to zero.
+ */
+void ec_fsm_pdo_conf_state_zero_pdo_count(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe))
+        return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_WARN("Failed to clear Pdo assignment of SM%u.\n", fsm->sync_index);
+        fsm->state = ec_fsm_pdo_state_error;
+        return;
+    }
+
+    // the sync manager's assigned Pdos have been cleared
+    ec_pdo_list_clear_pdos(&fsm->sync->pdos);
+
+    // assign all Pdos belonging to the current sync manager
+    
+    // find first Pdo
+    if (!(fsm->pdo = ec_fsm_pdo_conf_action_next_pdo(fsm, &fsm->pdos.list))) {
+
+        if (fsm->slave->master->debug_level)
+            EC_DBG("No Pdos to assign.\n");
+
+        // check for mapping to be altered
+        ec_fsm_pdo_conf_action_next_sync(fsm);
+        return;
+    }
+
+    // assign first Pdo
+    fsm->pdo_pos = 1;
+	ec_fsm_pdo_conf_action_assign_pdo(fsm);
+}
+
+/*****************************************************************************/
+
+/** Assign a Pdo.
+ */
+void ec_fsm_pdo_conf_action_assign_pdo(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration 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_pos);
+    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_pos);
+    
+    fsm->state = ec_fsm_pdo_conf_state_assign_pdo;
+    ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
+    ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
+}
+
+/*****************************************************************************/
+
+/** Add a Pdo to the sync managers Pdo assignment.
+ */
+void ec_fsm_pdo_conf_state_assign_pdo(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_WARN("Failed to assign Pdo 0x%04X at position %u of SM%u.\n",
+                fsm->pdo->index, fsm->pdo_pos, fsm->sync_index);
+        fsm->state = ec_fsm_pdo_state_error;
+        return;
+    }
+
+    // find next Pdo
+    if (!(fsm->pdo = ec_fsm_pdo_conf_action_next_pdo(fsm, &fsm->pdo->list))) {
+
+        // no more Pdos to assign, set Pdo count
+        EC_WRITE_U8(fsm->request.data, fsm->pdo_pos);
+        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_pos);
+        
+        fsm->state = ec_fsm_pdo_conf_state_set_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_pos++;
+    ec_fsm_pdo_conf_action_assign_pdo(fsm);
+}
+    
+/*****************************************************************************/
+
+/** Set the number of assigned Pdos.
+ */
+void ec_fsm_pdo_conf_state_set_pdo_count(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_WARN("Failed to set number of assigned Pdos of SM%u.\n",
+                fsm->sync_index);
+        fsm->state = ec_fsm_pdo_state_error;
+        return;
+    }
+
+    // Pdos have been configured
+    ec_pdo_list_copy(&fsm->sync->pdos, &fsm->pdos);
+
+    if (fsm->slave->master->debug_level)
+        EC_DBG("Successfully configured Pdo assignment of SM%u.\n",
+                fsm->sync_index);
+
+    // check if Pdo mapping has to be altered
+    ec_fsm_pdo_conf_action_next_sync(fsm);
+}
+
+/******************************************************************************
+ * Common state functions
+ *****************************************************************************/
+
+/** State: ERROR.
+ */
+void ec_fsm_pdo_state_error(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+}
+
+/*****************************************************************************/
+
+/** State: END.
+ */
+void ec_fsm_pdo_state_end(
+        ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */
+        )
+{
+}
+
+/*****************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/fsm_pdo.h	Thu Jul 31 16:13:29 2008 +0000
@@ -0,0 +1,90 @@
+/******************************************************************************
+ *
+ *  $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_H__
+#define __EC_FSM_PDO_H__
+
+#include "../include/ecrt.h"
+
+#include "globals.h"
+#include "datagram.h"
+#include "fsm_coe.h"
+#include "fsm_pdo_entry.h"
+
+/*****************************************************************************/
+
+/**
+ * \see ec_fsm_pdo
+ */
+typedef struct ec_fsm_pdo ec_fsm_pdo_t;
+
+/** Pdo configuration state machine.
+ */
+struct ec_fsm_pdo
+{
+    void (*state)(ec_fsm_pdo_t *); /**< State function. */
+    ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use. */
+    ec_fsm_pdo_entry_t fsm_pdo_entry; /**< Pdo entry state machine. */
+    ec_pdo_list_t pdos; /**< Pdo configuration. */
+    ec_sdo_request_t request; /**< Sdo request. */
+    ec_pdo_t slave_pdo; /**< Pdo actually appearing in a slave. */
+
+    ec_slave_t *slave; /**< Slave the FSM runs on. */
+    uint8_t sync_index; /**< Current sync manager index. */
+    ec_sync_t *sync; /**< Current sync manager. */
+    ec_pdo_t *pdo; /**< Current Pdo. */
+    unsigned int pdo_pos; /**< Assignment position of current Pdos. */
+    unsigned int pdo_count; /**< Number of assigned Pdos. */
+};
+
+/*****************************************************************************/
+
+void ec_fsm_pdo_init(ec_fsm_pdo_t *, ec_fsm_coe_t *);
+void ec_fsm_pdo_clear(ec_fsm_pdo_t *);
+
+void ec_fsm_pdo_start_reading(ec_fsm_pdo_t *, ec_slave_t *);
+void ec_fsm_pdo_start_configuration(ec_fsm_pdo_t *, ec_slave_t *);
+
+int ec_fsm_pdo_exec(ec_fsm_pdo_t *);
+int ec_fsm_pdo_success(const ec_fsm_pdo_t *);
+
+/*****************************************************************************/
+
+#endif
--- a/master/fsm_pdo_assign.c	Thu Jul 31 09:30:38 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,389 +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 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_sync(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->sync_index = 0xff; // next is zero
-    fsm->num_configured_syncs = 0;
-    ec_fsm_pdo_assign_next_sync(fsm);
-}
-
-/*****************************************************************************/
-
-/** Process Pdo assignment of next sync manager.
- */
-void ec_fsm_pdo_assign_next_sync(
-        ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */
-        )
-{
-    fsm->sync_index++;
-
-    for (; fsm->sync_index < EC_MAX_SYNC_MANAGERS; fsm->sync_index++) {
-        fsm->pdos = &fsm->slave->config->sync_configs[fsm->sync_index].pdos;
-        
-        if (!(fsm->sync = ec_slave_get_sync(fsm->slave, fsm->sync_index))) {
-            if (!list_empty(&fsm->pdos->list)) {
-                EC_WARN("Slave %u does not provide a configuration "
-                        "for SM%u!\n", fsm->slave->ring_position,
-                        fsm->sync_index);
-                fsm->state = ec_fsm_pdo_assign_state_error;
-                return;
-            }
-            continue;
-        }
-
-        // check if assignment has to be altered
-        if (ec_pdo_list_equal(&fsm->sync->pdos, fsm->pdos))
-            continue;
-
-        if (fsm->slave->master->debug_level) {
-            EC_DBG("Pdo assignment of SM%u differs:\n", fsm->sync_index);
-            EC_DBG("Currently assigned Pdos: ");
-            ec_pdo_list_print(&fsm->sync->pdos);
-            printk("\n");
-            EC_DBG("Pdos to assign: ");
-            ec_pdo_list_print(fsm->pdos);
-            printk("\n");
-        }
-
-        // Pdo assignment has to be changed. Does the slave support this?
-        if (!(fsm->slave->sii.mailbox_protocols & EC_MBOX_COE)
-                || (fsm->slave->sii.has_general
-                    && !fsm->slave->sii.coe_details.enable_pdo_assign)) {
-            EC_WARN("Slave %u does not support assigning Pdos!\n",
-                    fsm->slave->ring_position);
-            fsm->state = ec_fsm_pdo_assign_state_error;
-            return;
-        }
-
-        fsm->num_configured_syncs++;
-
-        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.\n");
-
-        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 && !fsm->num_configured_syncs)
-        EC_DBG("Pdo assignments are already configured correctly.\n");
-    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_WARN("Failed to clear Pdo assignment of SM%u.\n", fsm->sync_index);
-        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.\n");
-        ec_fsm_pdo_assign_next_sync(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_WARN("Failed to assign Pdo 0x%04X to position %u in SM%u.\n",
-                fsm->pdo->index, fsm->pdo_count, fsm->sync_index);
-        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_WARN("Failed to set number of assigned Pdos for SM%u.\n",
-                fsm->sync_index);
-        fsm->state = ec_fsm_pdo_assign_state_error;
-        return;
-    }
-
-    if (fsm->slave->master->debug_level)
-        EC_DBG("Pdo assignment successful for SM%u.\n", fsm->sync_index);
-
-    // assignment for this sync manager finished
-    ec_fsm_pdo_assign_next_sync(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. */
-        )
-{
-}
-
-/*****************************************************************************/
--- a/master/fsm_pdo_assign.h	Thu Jul 31 09:30:38 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +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 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. */
-
-    uint8_t sync_index; /**< Current sync manager index. */
-    const ec_pdo_list_t *pdos; /**< Target Pdo assignment. */
-    const ec_sync_t *sync; /**< Current sync manager. */
-    unsigned int num_configured_syncs; /**< Number of configured
-                                         assignments. */
-    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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/fsm_pdo_entry.c	Thu Jul 31 16:13:29 2008 +0000
@@ -0,0 +1,500 @@
+/******************************************************************************
+ *
+ *  $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 state machine.
+ */
+
+/*****************************************************************************/
+
+#include "globals.h"
+#include "master.h"
+#include "mailbox.h"
+#include "slave_config.h"
+
+#include "fsm_pdo_entry.h"
+
+/*****************************************************************************/
+
+void ec_fsm_pdo_entry_read_state_start(ec_fsm_pdo_entry_t *);
+void ec_fsm_pdo_entry_read_state_count(ec_fsm_pdo_entry_t *);
+void ec_fsm_pdo_entry_read_state_entry(ec_fsm_pdo_entry_t *);
+
+void ec_fsm_pdo_entry_read_action_next(ec_fsm_pdo_entry_t *);
+
+void ec_fsm_pdo_entry_conf_state_start(ec_fsm_pdo_entry_t *);
+void ec_fsm_pdo_entry_conf_state_zero_entry_count(ec_fsm_pdo_entry_t *);
+void ec_fsm_pdo_entry_conf_state_map_entry(ec_fsm_pdo_entry_t *);
+void ec_fsm_pdo_entry_conf_state_set_entry_count(ec_fsm_pdo_entry_t *);
+
+void ec_fsm_pdo_entry_state_end(ec_fsm_pdo_entry_t *);
+void ec_fsm_pdo_entry_state_error(ec_fsm_pdo_entry_t *);
+
+/*****************************************************************************/
+
+/** Constructor.
+ */
+void ec_fsm_pdo_entry_init(
+        ec_fsm_pdo_entry_t *fsm, /**< Pdo mapping 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_entry_clear(
+        ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    ec_sdo_request_clear(&fsm->request);
+}
+
+/*****************************************************************************/
+
+/** Start reading a Pdo's entries.
+ */
+void ec_fsm_pdo_entry_start_reading(
+        ec_fsm_pdo_entry_t *fsm, /**< Pdo mapping state machine. */
+        ec_slave_t *slave, /**< slave to configure */
+        ec_pdo_t *pdo /**< Pdo to read entries for. */
+        )
+{
+    fsm->slave = slave;
+    fsm->target_pdo = pdo;
+
+    ec_pdo_clear_entries(fsm->target_pdo);
+    
+    fsm->state = ec_fsm_pdo_entry_read_state_start;
+}
+
+/*****************************************************************************/
+
+/** Start Pdo mapping state machine.
+ */
+void ec_fsm_pdo_entry_start_configuration(
+        ec_fsm_pdo_entry_t *fsm, /**< Pdo mapping state machine. */
+        ec_slave_t *slave, /**< slave to configure */
+        const ec_pdo_t *pdo /**< Pdo with the desired entries. */
+        )
+{
+    fsm->slave = slave;
+    fsm->source_pdo = pdo;
+
+    fsm->state = ec_fsm_pdo_entry_conf_state_start;
+}
+
+/*****************************************************************************/
+
+/** Get running state.
+ *
+ * \return false, if state machine has terminated
+ */
+int ec_fsm_pdo_entry_running(
+        const ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    return fsm->state != ec_fsm_pdo_entry_state_end
+        && fsm->state != ec_fsm_pdo_entry_state_error;
+}
+
+/*****************************************************************************/
+
+/** Executes the current state.
+ *
+ * \return false, if state machine has terminated
+ */
+int ec_fsm_pdo_entry_exec(
+        ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    fsm->state(fsm);
+    return ec_fsm_pdo_entry_running(fsm);
+}
+
+/*****************************************************************************/
+
+/** Get execution result.
+ *
+ * \return true, if the state machine terminated gracefully
+ */
+int ec_fsm_pdo_entry_success(
+        const ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    return fsm->state == ec_fsm_pdo_entry_state_end;
+}
+
+/******************************************************************************
+ * Reading state functions.
+ *****************************************************************************/
+
+/** Request reading the number of mapped Pdo entries.
+ */
+void ec_fsm_pdo_entry_read_state_start(
+        ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    ec_sdo_request_address(&fsm->request, fsm->target_pdo->index, 0);
+    ecrt_sdo_request_read(&fsm->request);
+
+    fsm->state = ec_fsm_pdo_entry_read_state_count;
+    ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
+    ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
+}
+
+/*****************************************************************************/
+
+/** Read number of mapped Pdo entries.
+ */
+void ec_fsm_pdo_entry_read_state_count(
+        ec_fsm_pdo_entry_t *fsm /**< finite state machine */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe))
+        return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_ERR("Failed to read number of mapped Pdo entries.\n");
+        fsm->state = ec_fsm_pdo_entry_state_error;
+        return;
+    }
+
+    if (fsm->request.data_size != sizeof(uint8_t)) {
+        EC_ERR("Invalid data size %u at uploading Sdo 0x%04X:%02X.\n",
+                fsm->request.data_size, fsm->request.index,
+                fsm->request.subindex);
+        fsm->state = ec_fsm_pdo_entry_state_error;
+        return;
+    }
+
+    fsm->entry_count = EC_READ_U8(fsm->request.data);
+
+    if (fsm->slave->master->debug_level)
+        EC_DBG("%u Pdo entries mapped.\n", fsm->entry_count);
+
+    // read first Pdo entry
+    fsm->entry_pos = 1;
+    ec_fsm_pdo_entry_read_action_next(fsm);
+}
+
+/*****************************************************************************/
+
+/** Read next Pdo entry.
+ */
+void ec_fsm_pdo_entry_read_action_next(
+        ec_fsm_pdo_entry_t *fsm /**< finite state machine */
+        )
+{
+    if (fsm->entry_pos <= fsm->entry_count) {
+        ec_sdo_request_address(&fsm->request, fsm->target_pdo->index, fsm->entry_pos);
+        ecrt_sdo_request_read(&fsm->request);
+        fsm->state = ec_fsm_pdo_entry_read_state_entry;
+        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
+        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
+        return;
+    }
+
+    // finished reading entries.
+    fsm->state = ec_fsm_pdo_entry_state_end;
+}
+
+/*****************************************************************************/
+
+/** Read Pdo entry information.
+ */
+void ec_fsm_pdo_entry_read_state_entry(
+        ec_fsm_pdo_entry_t *fsm /**< finite state machine */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_ERR("Failed to read mapped Pdo entry.\n");
+        fsm->state = ec_fsm_pdo_entry_state_error;
+        return;
+    }
+
+    if (fsm->request.data_size != sizeof(uint32_t)) {
+        EC_ERR("Invalid data size %u at uploading Sdo 0x%04X:%02X.\n",
+                fsm->request.data_size, fsm->request.index,
+                fsm->request.subindex);
+        fsm->state = ec_fsm_pdo_entry_state_error;
+    } else {
+        uint32_t pdo_entry_info;
+        ec_pdo_entry_t *pdo_entry;
+
+        pdo_entry_info = EC_READ_U32(fsm->request.data);
+
+        if (!(pdo_entry = (ec_pdo_entry_t *)
+                    kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
+            EC_ERR("Failed to allocate Pdo entry.\n");
+            fsm->state = ec_fsm_pdo_entry_state_error;
+            return;
+        }
+
+        ec_pdo_entry_init(pdo_entry);
+        pdo_entry->index = pdo_entry_info >> 16;
+        pdo_entry->subindex = (pdo_entry_info >> 8) & 0xFF;
+        pdo_entry->bit_length = pdo_entry_info & 0xFF;
+
+        if (!pdo_entry->index && !pdo_entry->subindex) {
+            if (ec_pdo_entry_set_name(pdo_entry, "Gap")) {
+                ec_pdo_entry_clear(pdo_entry);
+                kfree(pdo_entry);
+                fsm->state = ec_fsm_pdo_entry_state_error;
+                return;
+            }
+        }
+
+        if (fsm->slave->master->debug_level) {
+            EC_DBG("Pdo entry 0x%04X:%02X, %u bit, \"%s\".\n",
+                    pdo_entry->index, pdo_entry->subindex,
+                    pdo_entry->bit_length,
+                    pdo_entry->name ? pdo_entry->name : "???");
+        }
+
+        list_add_tail(&pdo_entry->list, &fsm->target_pdo->entries);
+
+        // next Pdo entry
+        fsm->entry_pos++;
+        ec_fsm_pdo_entry_read_action_next(fsm);
+    }
+}
+
+/******************************************************************************
+ * Configuration state functions.
+ *****************************************************************************/
+
+/** Start Pdo mapping.
+ */
+void ec_fsm_pdo_entry_conf_state_start(
+        ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    // 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_WARN("Slave %u does not support changing the Pdo mapping!\n",
+                fsm->slave->ring_position);
+        fsm->state = ec_fsm_pdo_entry_state_error;
+        return;
+    }
+
+    if (ec_sdo_request_alloc(&fsm->request, 4)) {
+        fsm->state = ec_fsm_pdo_entry_state_error;
+        return;
+    }
+
+    // set mapped Pdo entry count to zero
+    EC_WRITE_U8(fsm->request.data, 0);
+    fsm->request.data_size = 1;
+    ec_sdo_request_address(&fsm->request, fsm->source_pdo->index, 0);
+    ecrt_sdo_request_write(&fsm->request);
+
+    if (fsm->slave->master->debug_level)
+        EC_DBG("Setting entry count to zero.\n");
+
+    fsm->state = ec_fsm_pdo_entry_conf_state_zero_entry_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_entry_conf_next_entry(
+        const ec_fsm_pdo_entry_t *fsm, /**< Pdo mapping state machine. */
+        const struct list_head *list /**< current entry list item */
+        )
+{
+    list = list->next; 
+    if (list == &fsm->source_pdo->entries)
+        return NULL; // no next entry
+    return list_entry(list, ec_pdo_entry_t, list);
+}
+
+/*****************************************************************************/
+
+/** Set the number of mapped entries to zero.
+ */
+void ec_fsm_pdo_entry_conf_state_zero_entry_count(
+        ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe))
+        return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_WARN("Failed to clear Pdo mapping.\n");
+        fsm->state = ec_fsm_pdo_entry_state_error;
+        return;
+    }
+
+    // find first entry
+    if (!(fsm->entry = ec_fsm_pdo_entry_conf_next_entry(
+                    fsm, &fsm->source_pdo->entries))) {
+        
+        if (fsm->slave->master->debug_level)
+            EC_DBG("No entries to map.\n");
+
+        fsm->state = ec_fsm_pdo_entry_state_end; // finished
+        return;
+    }
+
+    // add first entry
+    fsm->entry_pos = 1;
+    ec_fsm_pdo_entry_conf_action_map(fsm);
+}
+
+/*****************************************************************************/
+
+/** Starts to add a Pdo entry.
+ */
+void ec_fsm_pdo_entry_conf_action_map(
+        ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    uint32_t value;
+
+    if (fsm->slave->master->debug_level)
+        EC_DBG("Mapping Pdo entry 0x%04X:%02X (%u bit) at position %u.\n",
+                fsm->entry->index, fsm->entry->subindex,
+                fsm->entry->bit_length, fsm->entry_pos);
+
+    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->source_pdo->index, fsm->entry_pos);
+    ecrt_sdo_request_write(&fsm->request);
+    
+    fsm->state = ec_fsm_pdo_entry_conf_state_map_entry;
+    ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
+    ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
+}
+
+/*****************************************************************************/
+
+/** Add a Pdo entry.
+ */
+void ec_fsm_pdo_entry_conf_state_map_entry(
+        ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
+        EC_WARN("Failed to map Pdo entry 0x%04X:%02X (%u bit) to "
+                "position %u.\n", fsm->entry->index, fsm->entry->subindex,
+                fsm->entry->bit_length, fsm->entry_pos);
+        fsm->state = ec_fsm_pdo_entry_state_error;
+        return;
+    }
+
+    // find next entry
+    if (!(fsm->entry = ec_fsm_pdo_entry_conf_next_entry(
+                    fsm, &fsm->entry->list))) {
+
+        // No more entries to add. Write entry count.
+        EC_WRITE_U8(fsm->request.data, fsm->entry_pos);
+        fsm->request.data_size = 1;
+        ec_sdo_request_address(&fsm->request, fsm->source_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_pos);
+        
+        fsm->state = ec_fsm_pdo_entry_conf_state_set_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_pos++;
+    ec_fsm_pdo_entry_conf_action_map(fsm);
+}
+
+/*****************************************************************************/
+
+/** Set the number of entries.
+ */
+void ec_fsm_pdo_entry_conf_state_set_entry_count(
+        ec_fsm_pdo_entry_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 entries.\n");
+        fsm->state = ec_fsm_pdo_entry_state_error;
+        return;
+    }
+
+    if (fsm->slave->master->debug_level)
+        EC_DBG("Successfully configured mapping for Pdo 0x%04X.\n",
+                fsm->source_pdo->index);
+
+    fsm->state = ec_fsm_pdo_entry_state_end; // finished
+}
+
+/******************************************************************************
+ * Common state functions
+ *****************************************************************************/
+
+/** State: ERROR.
+ */
+void ec_fsm_pdo_entry_state_error(
+        ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+}
+
+/*****************************************************************************/
+
+/** State: END.
+ */
+void ec_fsm_pdo_entry_state_end(
+        ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */
+        )
+{
+}
+
+/*****************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/fsm_pdo_entry.h	Thu Jul 31 16:13:29 2008 +0000
@@ -0,0 +1,86 @@
+/******************************************************************************
+ *
+ *  $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 entry configuration state machine structures.
+ */
+
+/*****************************************************************************/
+
+#ifndef __EC_FSM_PDO_ENTRY_H__
+#define __EC_FSM_PDO_ENTRY_H__
+
+#include "globals.h"
+#include "../include/ecrt.h"
+#include "datagram.h"
+#include "fsm_coe.h"
+
+/*****************************************************************************/
+
+/**
+ * \see ec_fsm_pdo_entry
+ */
+typedef struct ec_fsm_pdo_entry ec_fsm_pdo_entry_t;
+
+/** Pdo configuration state machine.
+ */
+struct ec_fsm_pdo_entry
+{
+    void (*state)(ec_fsm_pdo_entry_t *); /**< state function */
+    ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use */
+    ec_sdo_request_t request; /**< Sdo request. */
+
+    ec_slave_t *slave; /**< Slave the FSM runs on. */
+    ec_pdo_t *target_pdo; /**< Pdo to read the mapping for. */
+    const ec_pdo_t *source_pdo; /**< Pdo with desired mapping. */
+    const ec_pdo_entry_t *entry; /**< Current entry. */
+    unsigned int entry_count; /**< Number of entries. */
+    unsigned int entry_pos; /**< Position in Pdo mapping. */
+};
+
+/*****************************************************************************/
+
+void ec_fsm_pdo_entry_init(ec_fsm_pdo_entry_t *, ec_fsm_coe_t *);
+void ec_fsm_pdo_entry_clear(ec_fsm_pdo_entry_t *);
+
+void ec_fsm_pdo_entry_start_reading(ec_fsm_pdo_entry_t *, ec_slave_t *,
+        ec_pdo_t *);
+void ec_fsm_pdo_entry_start_configuration(ec_fsm_pdo_entry_t *, ec_slave_t *,
+        const ec_pdo_t *);
+
+int ec_fsm_pdo_entry_exec(ec_fsm_pdo_entry_t *);
+int ec_fsm_pdo_entry_success(const ec_fsm_pdo_entry_t *);
+
+/*****************************************************************************/
+
+#endif
--- a/master/fsm_pdo_mapping.c	Thu Jul 31 09:30:38 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,383 +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 state machine.
- */
-
-/*****************************************************************************/
-
-#include "globals.h"
-#include "master.h"
-#include "mailbox.h"
-#include "slave_config.h"
-
-#include "fsm_pdo_mapping.h"
-
-/*****************************************************************************/
-
-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_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_pdo(ec_fsm_pdo_mapping_t *);
-
-/*****************************************************************************/
-
-/** Constructor.
- */
-void ec_fsm_pdo_mapping_init(
-        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;
-    ec_sdo_request_init(&fsm->request);
-}
-
-/*****************************************************************************/
-
-/** Destructor.
- */
-void ec_fsm_pdo_mapping_clear(
-        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
-        )
-{
-    ec_sdo_request_clear(&fsm->request);
-}
-
-/*****************************************************************************/
-
-/** Start Pdo mapping state machine.
- */
-void ec_fsm_pdo_mapping_start(
-        ec_fsm_pdo_mapping_t *fsm, /**< Pdo mapping state machine. */
-        ec_slave_t *slave /**< slave to configure */
-        )
-{
-    fsm->slave = slave;
-    fsm->state = ec_fsm_pdo_mapping_state_start;
-}
-
-/*****************************************************************************/
-
-/** Get running state.
- *
- * \return false, if state machine has terminated
- */
-int ec_fsm_pdo_mapping_running(
-        const ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
-        )
-{
-    return fsm->state != ec_fsm_pdo_mapping_state_end
-        && fsm->state != ec_fsm_pdo_mapping_state_error;
-}
-
-/*****************************************************************************/
-
-/** Executes the current state.
- *
- * \return false, if state machine has terminated
- */
-int ec_fsm_pdo_mapping_exec(
-        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
-        )
-{
-    fsm->state(fsm);
-    return ec_fsm_pdo_mapping_running(fsm);
-}
-
-/*****************************************************************************/
-
-/** Get execution result.
- *
- * \return true, if the state machine terminated gracefully
- */
-int ec_fsm_pdo_mapping_success(
-        const ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
-        )
-{
-    return fsm->state == ec_fsm_pdo_mapping_state_end;
-}
-
-/******************************************************************************
- * State functions.
- *****************************************************************************/
-
-/** Start Pdo mapping.
- */
-void ec_fsm_pdo_mapping_state_start(
-        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
-        )
-{
-    if (!fsm->slave->config) {
-        fsm->state = ec_fsm_pdo_mapping_state_end;
-        return;
-    }
-
-    fsm->pdo = NULL;
-    fsm->num_configured_pdos = 0;
-    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. */
-        )
-{
-    uint8_t sync_index;
-    const ec_pdo_list_t *pdos;
-    const ec_pdo_t *pdo, *assigned_pdo;
-    
-    for (sync_index = 0; sync_index < EC_MAX_SYNC_MANAGERS; sync_index++) {
-        pdos = &fsm->slave->config->sync_configs[sync_index].pdos;
-
-        list_for_each_entry(pdo, &pdos->list, list) {
-            if (fsm->pdo) { // there was a Pdo mapping changed in the last run
-                if (pdo == fsm->pdo) // this is the previously configured 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;
-                fsm->num_configured_pdos++;
-                break;
-            }
-        }
-    }
-
-    if (!fsm->pdo) {
-        if (fsm->slave->master->debug_level && !fsm->num_configured_pdos)
-            EC_DBG("Pdo mappings are already configured correctly.\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_WARN("Slave %u does not support Pdo mapping configuration!\n",
-                fsm->slave->ring_position);
-        fsm->state = ec_fsm_pdo_mapping_state_error;
-        return;
-    }
-
-    if (fsm->slave->master->debug_level) {
-        EC_DBG("Changing mapping of Pdo 0x%04X.\n", fsm->pdo->index);
-    }
-
-    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("Setting entry count to zero.\n");
-
-    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
-}
-
-/*****************************************************************************/
-
-/** 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;
-
-    if (fsm->slave->master->debug_level)
-        EC_DBG("Mapping Pdo entry 0x%04X:%02X (%u bit) at position %u.\n",
-                fsm->entry->index, fsm->entry->subindex,
-                fsm->entry->bit_length, fsm->entry_count);
-
-    value = fsm->entry->index << 16
-        | fsm->entry->subindex << 8 | fsm->entry->bit_length;
-    EC_WRITE_U32(fsm->request.data, value);
-    fsm->request.data_size = 4;
-    ec_sdo_request_address(&fsm->request, fsm->pdo->index, fsm->entry_count);
-    ecrt_sdo_request_write(&fsm->request);
-    
-    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 /**< Pdo mapping state machine. */
-        )
-{
-    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
-
-    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
-        EC_WARN("Failed to clear mapping of Pdo 0x%04X.\n", fsm->pdo->index);
-        fsm->state = ec_fsm_pdo_mapping_state_error;
-        return;
-    }
-
-    // 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 entries to map.\n");
-        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_WARN("Failed to map Pdo entry 0x%04X:%02X at 0x%04X:%02X.\n",
-                fsm->entry->index, fsm->entry->subindex, fsm->pdo->index,
-                fsm->entry_count);
-        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, 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_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 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_WARN("Failed to set number of entries for Pdo 0x%04X.\n",
-                fsm->pdo->index);
-        fsm->state = ec_fsm_pdo_mapping_state_error;
-        return;
-    }
-
-    if (fsm->slave->master->debug_level)
-        EC_DBG("Pdo mapping configuration successful.\n");
-
-    ec_fsm_pdo_mapping_next_pdo(fsm);
-}
-
-/******************************************************************************
- * Common state functions
- *****************************************************************************/
-
-/** State: ERROR.
- */
-void ec_fsm_pdo_mapping_state_error(
-        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
-        )
-{
-}
-
-/*****************************************************************************/
-
-/** State: END.
- */
-void ec_fsm_pdo_mapping_state_end(
-        ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */
-        )
-{
-}
-
-/*****************************************************************************/
--- a/master/fsm_pdo_mapping.h	Thu Jul 31 09:30:38 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 configuration state machine structures.
- */
-
-/*****************************************************************************/
-
-#ifndef __EC_FSM_PDO_MAPPING_H__
-#define __EC_FSM_PDO_MAPPING_H__
-
-#include "globals.h"
-#include "../include/ecrt.h"
-#include "datagram.h"
-#include "fsm_coe.h"
-
-/*****************************************************************************/
-
-/**
- * \see ec_fsm_pdo_mapping
- */
-typedef struct ec_fsm_pdo_mapping ec_fsm_pdo_mapping_t;
-
-/** 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 */
-    ec_slave_t *slave; /**< Slave the FSM runs on. */
-
-    const ec_pdo_t *pdo; /**< Current Pdo to configure. */
-    unsigned int num_configured_pdos; /**< Number of configured Pdos. */
-    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_mapping_init(ec_fsm_pdo_mapping_t *, ec_fsm_coe_t *);
-void ec_fsm_pdo_mapping_clear(ec_fsm_pdo_mapping_t *);
-
-void ec_fsm_pdo_mapping_start(ec_fsm_pdo_mapping_t *, ec_slave_t *);
-int ec_fsm_pdo_mapping_exec(ec_fsm_pdo_mapping_t *);
-int ec_fsm_pdo_mapping_success(const ec_fsm_pdo_mapping_t *);
-
-/*****************************************************************************/
-
-#endif
--- a/master/fsm_slave_config.c	Thu Jul 31 09:30:38 2008 +0000
+++ b/master/fsm_slave_config.c	Thu Jul 31 16:13:29 2008 +0000
@@ -53,8 +53,7 @@
 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_pdo_sync(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_conf(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 *);
 void ec_fsm_slave_config_state_op(ec_fsm_slave_config_t *);
@@ -75,16 +74,16 @@
  */
 void ec_fsm_slave_config_init(
         ec_fsm_slave_config_t *fsm, /**< slave state machine */
-        ec_datagram_t *datagram /**< datagram structure to use */
+        ec_datagram_t *datagram, /**< datagram structure to use */
+        ec_fsm_change_t *fsm_change, /**< State change state machine to use. */
+        ec_fsm_coe_t *fsm_coe, /**< CoE state machine to use. */
+        ec_fsm_pdo_t *fsm_pdo /**< Pdo configuration state machine to use. */
         )
 {
     fsm->datagram = datagram;
-
-    // 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_assign_init(&fsm->fsm_pdo_assign, &fsm->fsm_coe);
-    ec_fsm_pdo_mapping_init(&fsm->fsm_pdo_mapping, &fsm->fsm_coe);
+    fsm->fsm_change = fsm_change;
+    fsm->fsm_coe = fsm_coe;
+    fsm->fsm_pdo = fsm_pdo;
 }
 
 /*****************************************************************************/
@@ -95,11 +94,6 @@
         ec_fsm_slave_config_t *fsm /**< slave state machine */
         )
 {
-    // clear sub state machines
-    ec_fsm_change_clear(&fsm->fsm_change);
-    ec_fsm_coe_clear(&fsm->fsm_coe);
-    ec_fsm_pdo_assign_clear(&fsm->fsm_pdo_assign);
-    ec_fsm_pdo_mapping_clear(&fsm->fsm_pdo_mapping);
 }
 
 /*****************************************************************************/
@@ -181,8 +175,8 @@
     // force flag
     fsm->slave->force_config = 0;
 
-    ec_fsm_change_start(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT);
-    ec_fsm_change_exec(&fsm->fsm_change);
+    ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT);
+    ec_fsm_change_exec(fsm->fsm_change);
     fsm->state = ec_fsm_slave_config_state_init;
 }
 
@@ -198,10 +192,10 @@
     ec_slave_t *slave = fsm->slave;
     ec_datagram_t *datagram = fsm->datagram;
 
-    if (ec_fsm_change_exec(&fsm->fsm_change)) return;
-
-    if (!ec_fsm_change_success(&fsm->fsm_change)) {
-        if (!fsm->fsm_change.spontaneous_change)
+    if (ec_fsm_change_exec(fsm->fsm_change)) return;
+
+    if (!ec_fsm_change_success(fsm->fsm_change)) {
+        if (!fsm->fsm_change->spontaneous_change)
             slave->error_flag = 1;
         fsm->state = ec_fsm_slave_config_state_error;
         return;
@@ -385,8 +379,8 @@
         )
 {
     fsm->state = ec_fsm_slave_config_state_preop;
-    ec_fsm_change_start(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_PREOP);
-    ec_fsm_change_exec(&fsm->fsm_change); // execute immediately
+    ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_PREOP);
+    ec_fsm_change_exec(fsm->fsm_change); // execute immediately
 }
 
 /*****************************************************************************/
@@ -400,10 +394,10 @@
     ec_slave_t *slave = fsm->slave;
     ec_master_t *master = fsm->slave->master;
 
-    if (ec_fsm_change_exec(&fsm->fsm_change)) return;
-
-    if (!ec_fsm_change_success(&fsm->fsm_change)) {
-        if (!fsm->fsm_change.spontaneous_change)
+    if (ec_fsm_change_exec(fsm->fsm_change)) return;
+
+    if (!ec_fsm_change_success(fsm->fsm_change)) {
+        if (!fsm->fsm_change->spontaneous_change)
             slave->error_flag = 1;
         fsm->state = ec_fsm_slave_config_state_error;
         return;
@@ -455,8 +449,8 @@
     fsm->request = list_entry(fsm->slave->config->sdo_configs.next,
             ec_sdo_request_t, list);
     ecrt_sdo_request_write(fsm->request);
-    ec_fsm_coe_transfer(&fsm->fsm_coe, fsm->slave, fsm->request);
-    ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
+    ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, fsm->request);
+    ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
 }
 
 /*****************************************************************************/
@@ -467,9 +461,9 @@
         ec_fsm_slave_config_t *fsm /**< slave state machine */
         )
 {
-    if (ec_fsm_coe_exec(&fsm->fsm_coe)) return;
-
-    if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
+    if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
+
+    if (!ec_fsm_coe_success(fsm->fsm_coe)) {
         EC_ERR("Sdo configuration failed for slave %u.\n",
                 fsm->slave->ring_position);
         fsm->slave->error_flag = 1;
@@ -482,8 +476,8 @@
         fsm->request = list_entry(fsm->request->list.next, ec_sdo_request_t,
                 list);
         ecrt_sdo_request_write(fsm->request);
-        ec_fsm_coe_transfer(&fsm->fsm_coe, fsm->slave, fsm->request);
-        ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
+        ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, fsm->request);
+        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
         return;
     }
 
@@ -571,45 +565,25 @@
         return;
     }
 
-    // Start configuring Pdo mapping
-    ec_fsm_pdo_mapping_start(&fsm->fsm_pdo_mapping, fsm->slave);
-    fsm->state = ec_fsm_slave_config_state_pdo_mapping;
+    // Start configuring Pdos
+    ec_fsm_pdo_start_configuration(fsm->fsm_pdo, fsm->slave);
+    fsm->state = ec_fsm_slave_config_state_pdo_conf;
     fsm->state(fsm); // 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_mapping_exec(&fsm->fsm_pdo_mapping)) return;
-
-    if (!ec_fsm_pdo_mapping_success(&fsm->fsm_pdo_mapping)) {
-        EC_WARN("Configuration of Pdo mappings failed on slave %u.\n",
-                fsm->slave->ring_position);
-    }
-
-    // start applying Pdo assignments
-    ec_fsm_pdo_assign_start(&fsm->fsm_pdo_assign, fsm->slave);
-    fsm->state = ec_fsm_slave_config_state_pdo_assign;
-    fsm->state(fsm); // 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_assign_exec(&fsm->fsm_pdo_assign)) return;
-
-    if (!ec_fsm_pdo_assign_success(&fsm->fsm_pdo_assign)) {
-        EC_WARN("Configuration of Pdo assignments failed on slave %u.\n",
+/** Slave configuration state: PDO_CONF.
+ */
+void ec_fsm_slave_config_state_pdo_conf(
+        ec_fsm_slave_config_t *fsm /**< slave state machine */
+        )
+{
+    if (ec_fsm_pdo_exec(fsm->fsm_pdo))
+        return;
+
+    if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
+        EC_WARN("Pdo configuration failed on slave %u.\n",
                 fsm->slave->ring_position);
     }
 
@@ -708,8 +682,8 @@
         )
 {
     fsm->state = ec_fsm_slave_config_state_safeop;
-    ec_fsm_change_start(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_SAFEOP);
-    ec_fsm_change_exec(&fsm->fsm_change); // execute immediately
+    ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_SAFEOP);
+    ec_fsm_change_exec(fsm->fsm_change); // execute immediately
 }
 
 /*****************************************************************************/
@@ -723,10 +697,10 @@
     ec_master_t *master = fsm->slave->master;
     ec_slave_t *slave = fsm->slave;
 
-    if (ec_fsm_change_exec(&fsm->fsm_change)) return;
-
-    if (!ec_fsm_change_success(&fsm->fsm_change)) {
-        if (!fsm->fsm_change.spontaneous_change)
+    if (ec_fsm_change_exec(fsm->fsm_change)) return;
+
+    if (!ec_fsm_change_success(fsm->fsm_change)) {
+        if (!fsm->fsm_change->spontaneous_change)
             fsm->slave->error_flag = 1;
         fsm->state = ec_fsm_slave_config_state_error;
         return;
@@ -749,8 +723,8 @@
 
     // set state to OP
     fsm->state = ec_fsm_slave_config_state_op;
-    ec_fsm_change_start(&fsm->fsm_change, slave, EC_SLAVE_STATE_OP);
-    ec_fsm_change_exec(&fsm->fsm_change); // execute immediately
+    ec_fsm_change_start(fsm->fsm_change, slave, EC_SLAVE_STATE_OP);
+    ec_fsm_change_exec(fsm->fsm_change); // execute immediately
 }
 
 /*****************************************************************************/
@@ -764,10 +738,10 @@
     ec_master_t *master = fsm->slave->master;
     ec_slave_t *slave = fsm->slave;
 
-    if (ec_fsm_change_exec(&fsm->fsm_change)) return;
-
-    if (!ec_fsm_change_success(&fsm->fsm_change)) {
-        if (!fsm->fsm_change.spontaneous_change)
+    if (ec_fsm_change_exec(fsm->fsm_change)) return;
+
+    if (!ec_fsm_change_success(fsm->fsm_change)) {
+        if (!fsm->fsm_change->spontaneous_change)
             slave->error_flag = 1;
         fsm->state = ec_fsm_slave_config_state_error;
         return;
--- a/master/fsm_slave_config.h	Thu Jul 31 09:30:38 2008 +0000
+++ b/master/fsm_slave_config.h	Thu Jul 31 16:13:29 2008 +0000
@@ -48,8 +48,7 @@
 #include "datagram.h"
 #include "fsm_change.h"
 #include "fsm_coe.h"
-#include "fsm_pdo_assign.h"
-#include "fsm_pdo_mapping.h"
+#include "fsm_pdo.h"
 
 /*****************************************************************************/
 
@@ -60,21 +59,21 @@
  */
 struct ec_fsm_slave_config
 {
+    ec_datagram_t *datagram; /**< Datagram used in the state machine. */
+    ec_fsm_change_t *fsm_change; /**< State change state machine. */
+    ec_fsm_coe_t *fsm_coe; /**< CoE state machine. */
+    ec_fsm_pdo_t *fsm_pdo; /**< Pdo configuration state machine. */
+
     ec_slave_t *slave; /**< Slave the FSM runs on. */
-    ec_datagram_t *datagram; /**< Datagram used in the state machine. */
+    void (*state)(ec_fsm_slave_config_t *); /**< State function. */
     unsigned int retries; /**< Retries on datagram timeout. */
-
-    void (*state)(ec_fsm_slave_config_t *); /**< State function. */
     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_assign_t fsm_pdo_assign; /**< Pdo assignment state machine. */
-    ec_fsm_pdo_mapping_t fsm_pdo_mapping; /**< Pdo mapping state machine. */
 };
 
 /*****************************************************************************/
 
-void ec_fsm_slave_config_init(ec_fsm_slave_config_t *, ec_datagram_t *);
+void ec_fsm_slave_config_init(ec_fsm_slave_config_t *, ec_datagram_t *,
+        ec_fsm_change_t *, ec_fsm_coe_t *, ec_fsm_pdo_t *);
 void ec_fsm_slave_config_clear(ec_fsm_slave_config_t *);
 
 void ec_fsm_slave_config_start(ec_fsm_slave_config_t *, ec_slave_t *);
--- a/master/fsm_slave_scan.c	Thu Jul 31 09:30:38 2008 +0000
+++ b/master/fsm_slave_scan.c	Thu Jul 31 16:13:29 2008 +0000
@@ -72,13 +72,12 @@
         ec_datagram_t *datagram, /**< Datagram to use. */
         ec_fsm_slave_config_t *fsm_slave_config, /**< Slave configuration
                                                   state machine to use. */
-        ec_fsm_coe_map_t *fsm_coe_map /**< Pdo mapping state machine to use.
-                                       */
+        ec_fsm_pdo_t *fsm_pdo /**< Pdo configuration machine to use. */
         )
 {
     fsm->datagram = datagram;
     fsm->fsm_slave_config = fsm_slave_config;
-    fsm->fsm_coe_map = fsm_coe_map;
+    fsm->fsm_pdo = fsm_pdo;
 
     // init sub state machines
     ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
@@ -633,8 +632,8 @@
         EC_DBG("Scanning Pdo assignment and mapping of slave %u.\n",
                 slave->ring_position);
     fsm->state = ec_fsm_slave_scan_state_pdos;
-    ec_fsm_coe_map_start(fsm->fsm_coe_map, slave);
-    ec_fsm_coe_map_exec(fsm->fsm_coe_map); // execute immediately
+    ec_fsm_pdo_start_reading(fsm->fsm_pdo, slave);
+    ec_fsm_pdo_exec(fsm->fsm_pdo); // execute immediately
 }
 
 /*****************************************************************************/
@@ -645,15 +644,15 @@
         ec_fsm_slave_scan_t *fsm /**< slave state machine */
         )
 {
-    if (ec_fsm_coe_map_exec(fsm->fsm_coe_map))
-        return;
-
-    if (!ec_fsm_coe_map_success(fsm->fsm_coe_map)) {
-        fsm->state = ec_fsm_slave_scan_state_error;
-        return;
-    }
-
-    // fetching of Pdo assignment/mapping finished
+    if (ec_fsm_pdo_exec(fsm->fsm_pdo))
+        return;
+
+    if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
+        fsm->state = ec_fsm_slave_scan_state_error;
+        return;
+    }
+
+    // reading Pdo configuration finished
     fsm->state = ec_fsm_slave_scan_state_end;
 }
 
--- a/master/fsm_slave_scan.h	Thu Jul 31 09:30:38 2008 +0000
+++ b/master/fsm_slave_scan.h	Thu Jul 31 16:13:29 2008 +0000
@@ -49,7 +49,7 @@
 #include "fsm_sii.h"
 #include "fsm_change.h"
 #include "fsm_coe.h"
-#include "fsm_coe_map.h"
+#include "fsm_pdo.h"
 
 /*****************************************************************************/
 
@@ -64,7 +64,7 @@
     ec_datagram_t *datagram; /**< Datagram used in the state machine. */
     ec_fsm_slave_config_t *fsm_slave_config; /**< Slave configuration state
                                                machine to use. */
-    ec_fsm_coe_map_t *fsm_coe_map; /**< Pdo mapping state machine to use. */
+    ec_fsm_pdo_t *fsm_pdo; /**< Pdo configuration state machine to use. */
     unsigned int retries; /**< Retries on datagram timeout. */
 
     void (*state)(ec_fsm_slave_scan_t *); /**< State function. */
@@ -76,7 +76,7 @@
 /*****************************************************************************/
 
 void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *, ec_datagram_t *,
-        ec_fsm_slave_config_t *, ec_fsm_coe_map_t *);
+        ec_fsm_slave_config_t *, ec_fsm_pdo_t *);
 void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *);
 
 void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *, ec_slave_t *);