Reading of Pdo mapping via CoE during scan.
authorFlorian Pose <fp@igh-essen.com>
Tue, 26 Feb 2008 16:58:20 +0000
changeset 831 ded9519c8d6e
parent 830 d83d92e1a919
child 832 a5b4f1d17908
Reading of Pdo mapping via CoE during scan.
NEWS
TODO
documentation/graphs/fsm_master.dot
master/canopen.c
master/canopen.h
master/fsm_coe.c
master/fsm_coe_map.c
master/fsm_coe_map.h
master/fsm_master.c
master/fsm_slave_scan.c
master/fsm_slave_scan.h
master/slave.c
master/slave.h
--- a/NEWS	Tue Feb 26 13:20:32 2008 +0000
+++ b/NEWS	Tue Feb 26 16:58:20 2008 +0000
@@ -41,7 +41,10 @@
       be reached by specifying an explicit Pdo mapping and registering those
       Pdo entries.
 * Pdo configuration is now supported.
+* Current Pdo mapping/configuration is now read during bus scan, without
+  using the Sdo dictionary.
 * Added 8139too driver for kernel 2.6.22, thanks to Erwin Burgstaller.
+* Added 8139too driver for kernel 2.6.23, thanks to Richard Hacker.
 * Added e1000 driver for kernel 2.6.22.
 * Added support for slaves that do not support the LRW datagram type. Separate
   domains have to be used for inputs and output.
--- a/TODO	Tue Feb 26 13:20:32 2008 +0000
+++ b/TODO	Tue Feb 26 16:58:20 2008 +0000
@@ -8,7 +8,6 @@
 
 Version 1.4.0:
 
-* Read PDO mapping via CoE during bus scan.
 * Realtime interface changes:
     - SDO access.
 * Mailbox handler
@@ -18,9 +17,8 @@
 * Remove ecdb.h and let lsec output PDO information 'cut-and-pastable' for
   applications.
 * SDO write access in sysfs.
+* Distributed clocks.
 * Update documentation.
-* Distributed clocks.
-* Safety-over-EtherCAT
 
 Future issues:
 
@@ -29,6 +27,8 @@
               to replace lsec.
     - Step 2: Move kernel threads to user space daemon with a TCP interface
               replacing the cdev.
+* Mailbox gateway.
+* Slave-to-slave communication.
 * Redundancy with 2 network adapters.
 * Interface/buffers for asynchronous domain IO.
 
--- a/documentation/graphs/fsm_master.dot	Tue Feb 26 13:20:32 2008 +0000
+++ b/documentation/graphs/fsm_master.dot	Tue Feb 26 16:58:20 2008 +0000
@@ -26,16 +26,16 @@
 
     action_configure -> configure_slave
 
+    action_process_states -> action_configure
+    action_process_states -> action_process_sdo
+    action_process_states -> sdodict
+    action_process_states -> action_process_eeprom
+    action_process_states -> end
+
     action_next_slave_state -> read_states
     action_next_slave_state -> validate_vendor
     action_next_slave_state -> action_process_states
 
-    action_process_states -> action_configure
-    action_process_states -> action_process_sdo
-    action_process_states -> action_process_eeprom
-    action_process_states -> sdodict
-    action_process_states -> end
-
     //read_states -> error
     read_states -> action_next_slave_state
     read_states -> acknowledge
@@ -50,8 +50,8 @@
     action_addresses -> rewrite_addresses
 
     //validate_product -> error
+    validate_product -> action_addresses
     validate_product -> validate_vendor
-    validate_product -> action_addresses
 
     //rewrite_addresses -> error
     rewrite_addresses -> end
@@ -67,6 +67,7 @@
     configure_slave -> end
 
     //write_eeprom -> error
+    write_eeprom -> action_process_eeprom
     write_eeprom -> end
 
     //sdodict -> error
--- a/master/canopen.c	Tue Feb 26 13:20:32 2008 +0000
+++ b/master/canopen.c	Tue Feb 26 16:58:20 2008 +0000
@@ -416,7 +416,8 @@
     off_t off = 0;
     ec_sdo_request_t request;
 
-    ec_sdo_request_init_read(&request, entry);
+    ec_sdo_request_init_read(&request, entry->sdo->slave,
+            entry->sdo->index, entry->subindex);
 
     // schedule request.
     down(&master->sdo_sem);
@@ -479,11 +480,16 @@
    Sdo request constructor.
 */
 
-void ec_sdo_request_init_read(ec_sdo_request_t *req, /**< Sdo request */
-                              ec_sdo_entry_t *entry /**< Sdo entry */
-                              )
-{
-    req->entry = entry;
+void ec_sdo_request_init_read(
+        ec_sdo_request_t *req, /**< Sdo request */
+        ec_slave_t *slave, /**< Slave owning the Sdo. */
+        uint16_t index, /**< Sdo index. */
+        uint8_t subindex /**< Sdo subindex. */
+        )
+{
+    req->slave = slave;
+    req->index = index;
+    req->subindex = subindex;
     req->data = NULL;
     req->size = 0;
     req->state = EC_REQUEST_QUEUED;
--- a/master/canopen.h	Tue Feb 26 13:20:32 2008 +0000
+++ b/master/canopen.h	Tue Feb 26 16:58:20 2008 +0000
@@ -49,12 +49,9 @@
 
 /*****************************************************************************/
 
-/**
-   CANopen Sdo.
-*/
-
-struct ec_sdo
-{
+/** CANopen Sdo.
+ */
+struct ec_sdo {
     struct kobject kobj; /**< kobject */
     struct list_head list; /**< list item */
     ec_slave_t *slave; /**< parent slave */
@@ -67,12 +64,9 @@
 
 /*****************************************************************************/
 
-/**
-   CANopen Sdo entry.
-*/
-
-typedef struct
-{
+/** CANopen Sdo entry.
+ */
+typedef struct {
     struct kobject kobj; /**< kobject */
     struct list_head list; /**< list item */
     ec_sdo_t *sdo; /**< parent Sdo */
@@ -80,17 +74,13 @@
     uint16_t data_type; /**< entry data type */
     uint16_t bit_length; /**< entry length in bit */
     char *description; /**< entry description */
-}
-ec_sdo_entry_t;
+} ec_sdo_entry_t;
 
 /*****************************************************************************/
 
-/**
-   CANopen Sdo configuration data.
-*/
-
-typedef struct
-{
+/** CANopen Sdo configuration data.
+ */
+typedef struct {
     struct list_head list; /**< list item */
     uint16_t index; /**< Sdo index */
     uint8_t subindex; /**< Sdo subindex */
@@ -105,15 +95,15 @@
    CANopen Sdo request.
 */
 
-typedef struct
-{
+typedef struct {
     struct list_head list; /**< list item */
-    ec_sdo_entry_t *entry; /**< Sdo entry */
+    ec_slave_t *slave; /**< Slave owning the Sdo. */
+    uint16_t index; /**< Sdo index. */
+    uint8_t subindex; /**< Sdo subindex. */
     uint8_t *data; /**< pointer to Sdo data */
     size_t size; /**< size of Sdo data */
     ec_request_state_t state; /**< Sdo request state */
-}
-ec_sdo_request_t;
+} ec_sdo_request_t;
 
 /*****************************************************************************/
 
@@ -124,7 +114,8 @@
 int ec_sdo_entry_init(ec_sdo_entry_t *, uint8_t, ec_sdo_t *);
 void ec_sdo_entry_destroy(ec_sdo_entry_t *);
 
-void ec_sdo_request_init_read(ec_sdo_request_t *, ec_sdo_entry_t *);
+void ec_sdo_request_init_read(ec_sdo_request_t *, ec_slave_t *, uint16_t,
+        uint8_t);
 void ec_sdo_request_clear(ec_sdo_request_t *);
 
 /*****************************************************************************/
--- a/master/fsm_coe.c	Tue Feb 26 13:20:32 2008 +0000
+++ b/master/fsm_coe.c	Tue Feb 26 16:58:20 2008 +0000
@@ -1175,12 +1175,11 @@
     ec_slave_t *slave = fsm->slave;
     ec_master_t *master = slave->master;
     ec_sdo_request_t *request = fsm->request;
-    ec_sdo_entry_t *entry = request->entry;
     uint8_t *data;
 
     if (master->debug_level)
         EC_DBG("Uploading Sdo 0x%04X:%i from slave %i.\n",
-               entry->sdo->index, entry->subindex, slave->ring_position);
+               request->index, request->subindex, slave->ring_position);
 
     if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) {
         EC_ERR("Slave %u does not support CoE!\n", slave->ring_position);
@@ -1195,8 +1194,8 @@
 
     EC_WRITE_U16(data, 0x2 << 12); // Sdo request
     EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request
-    EC_WRITE_U16(data + 3, entry->sdo->index);
-    EC_WRITE_U8 (data + 5, entry->subindex);
+    EC_WRITE_U16(data + 3, request->index);
+    EC_WRITE_U8 (data + 5, request->subindex);
     memset(data + 6, 0x00, 4);
 
     if (master->debug_level) {
@@ -1311,7 +1310,6 @@
     uint8_t *data, mbox_prot;
     size_t rec_size, data_size;
     ec_sdo_request_t *request = fsm->request;
-    ec_sdo_entry_t *entry = request->entry;
     uint32_t complete_size;
     unsigned int expedited, size_specified;
 
@@ -1361,7 +1359,7 @@
     if (EC_READ_U16(data) >> 12 == 0x2 && // Sdo request
         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort Sdo transfer request
         EC_ERR("Sdo upload 0x%04X:%X aborted on slave %i.\n",
-               entry->sdo->index, entry->subindex, slave->ring_position);
+               request->index, request->subindex, slave->ring_position);
         if (rec_size >= 10)
             ec_canopen_abort_msg(EC_READ_U32(data + 6));
         else
@@ -1390,9 +1388,10 @@
 
         if (EC_READ_U16(data) >> 12 != 0x3 || // Sdo response
                 EC_READ_U8 (data + 2) >> 5 != 0x2 || // upload response
-                EC_READ_U16(data + 3) != entry->sdo->index || // index
-                EC_READ_U8 (data + 5) != entry->subindex) { // subindex
-            EC_ERR("Sdo upload 0x%04X:%X failed:\n", entry->sdo->index, entry->subindex);
+                EC_READ_U16(data + 3) != request->index || // index
+                EC_READ_U8 (data + 5) != request->subindex) { // subindex
+            EC_ERR("Sdo upload 0x%04X:%X failed:\n",
+                    request->index, request->subindex);
             EC_ERR("Invalid Sdo upload response at slave %i!\n",
                     slave->ring_position);
             ec_print_data(data, rec_size);
@@ -1438,9 +1437,10 @@
 
         if (EC_READ_U16(data) >> 12 != 0x3 || // Sdo response
                 EC_READ_U8 (data + 2) >> 5 != 0x2 || // upload response
-                EC_READ_U16(data + 3) != entry->sdo->index || // index
-                EC_READ_U8 (data + 5) != entry->subindex) { // subindex
-            EC_ERR("Sdo upload 0x%04X:%X failed:\n", entry->sdo->index, entry->subindex);
+                EC_READ_U16(data + 3) != request->index || // index
+                EC_READ_U8 (data + 5) != request->subindex) { // subindex
+            EC_ERR("Sdo upload 0x%04X:%X failed:\n",
+                    request->index, request->subindex);
             EC_ERR("Invalid Sdo upload response at slave %i!\n",
                     slave->ring_position);
             ec_print_data(data, rec_size);
@@ -1602,7 +1602,6 @@
     uint8_t *data, mbox_prot;
     size_t rec_size, data_size;
     ec_sdo_request_t *request = fsm->request;
-    ec_sdo_entry_t *entry = request->entry;
     uint32_t seg_size;
     unsigned int last_segment;
 
@@ -1652,7 +1651,7 @@
     if (EC_READ_U16(data) >> 12 == 0x2 && // Sdo request
         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort Sdo transfer request
         EC_ERR("Sdo upload 0x%04X:%X aborted on slave %i.\n",
-               entry->sdo->index, entry->subindex, slave->ring_position);
+               request->index, request->subindex, slave->ring_position);
         ec_canopen_abort_msg(EC_READ_U32(data + 6));
         fsm->state = ec_fsm_coe_error;
 	return;
@@ -1660,7 +1659,7 @@
 
     if (EC_READ_U16(data) >> 12 != 0x3 || // Sdo response
         EC_READ_U8 (data + 2) >> 5 != 0x0) { // upload segment response
-        EC_ERR("Sdo upload 0x%04X:%X failed:\n", entry->sdo->index, entry->subindex);
+        EC_ERR("Sdo upload 0x%04X:%X failed:\n", request->index, request->subindex);
         EC_ERR("Invalid Sdo upload segment response at slave %i!\n",
                slave->ring_position);
         ec_print_data(data, rec_size);
--- a/master/fsm_coe_map.c	Tue Feb 26 13:20:32 2008 +0000
+++ b/master/fsm_coe_map.c	Tue Feb 26 16:58:20 2008 +0000
@@ -55,7 +55,7 @@
 void ec_fsm_coe_map_state_end(ec_fsm_coe_map_t *);
 void ec_fsm_coe_map_state_error(ec_fsm_coe_map_t *);
 
-void ec_fsm_coe_map_action_next_sync(ec_fsm_coe_map_t *);
+void ec_fsm_coe_map_action_next_dir(ec_fsm_coe_map_t *);
 void ec_fsm_coe_map_action_next_pdo(ec_fsm_coe_map_t *);
 void ec_fsm_coe_map_action_next_pdo_entry(ec_fsm_coe_map_t *);
 
@@ -140,49 +140,56 @@
         ec_fsm_coe_map_t *fsm /**< finite state machine */
         )
 {
-    // read mapping of first sync manager
-    fsm->sync_index = 0;
-    ec_fsm_coe_map_action_next_sync(fsm);
-}
-
-/*****************************************************************************/
-
-/**
- * Read mapping of next sync manager.
- */
-
-void ec_fsm_coe_map_action_next_sync(
+    // read mapping for first direction
+    fsm->dir = (ec_direction_t) -1; // next is EC_DIR_OUTPUT
+    ec_fsm_coe_map_action_next_dir(fsm);
+}
+
+/*****************************************************************************/
+
+/**
+ * Read mapping of next direction manager.
+ */
+
+void ec_fsm_coe_map_action_next_dir(
         ec_fsm_coe_map_t *fsm /**< finite state machine */
         )
 {
     ec_slave_t *slave = fsm->slave;
-    ec_sdo_entry_t *entry;
-
-    for (; fsm->sync_index < slave->sii_sync_count; fsm->sync_index++) {
-        if (!(fsm->sync_sdo = ec_slave_get_sdo(slave, 0x1C10 + fsm->sync_index)))
+
+    fsm->dir++;
+
+    if (slave->master->debug_level)
+        EC_DBG("Processing dir %u of slave %u.\n",
+                fsm->dir, slave->ring_position);
+
+    for (; fsm->dir <= EC_DIR_INPUT; fsm->dir++) {
+
+        if (!(fsm->sync = ec_slave_get_pdo_sync(slave, fsm->dir))) {
+            if (slave->master->debug_level)
+                EC_DBG("No sync manager for direction %u!\n", fsm->dir);
             continue;
+        }
+
+        fsm->sync_sdo_index = 0x1C10 + fsm->sync->index;
 
         if (slave->master->debug_level)
             EC_DBG("Reading Pdo mapping of sync manager %u of slave %u.\n",
-                    fsm->sync_index, slave->ring_position);
+                    fsm->sync->index, slave->ring_position);
 
         ec_pdo_mapping_clear_pdos(&fsm->mapping);
 
-        if (!(entry = ec_sdo_get_entry(fsm->sync_sdo, 0))) {
-            EC_ERR("Sdo 0x%04X has no subindex 0 on slave %u.\n",
-                    fsm->sync_sdo->index,
-                    fsm->slave->ring_position);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
-
-        ec_sdo_request_init_read(&fsm->request, entry);
+        ec_sdo_request_init_read(&fsm->request, slave, fsm->sync_sdo_index, 0);
         fsm->state = ec_fsm_coe_map_state_pdo_count;
         ec_fsm_coe_upload(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 mapping finished for slave %u.\n",
+                slave->ring_position);
+
     fsm->state = ec_fsm_coe_map_state_end;
 }
 
@@ -225,41 +232,27 @@
         ec_fsm_coe_map_t *fsm /**< finite state machine */
         )
 {
-    ec_sdo_entry_t *entry;
-
     if (fsm->sync_subindex <= fsm->sync_subindices) {
-        if (!(entry = ec_sdo_get_entry(fsm->sync_sdo,
-                        fsm->sync_subindex))) {
-            EC_ERR("Sdo 0x%04X has no subindex %u on slave %u.\n",
-                    fsm->sync_sdo->index,
-                    fsm->sync_subindex,
-                    fsm->slave->ring_position);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
-
-        ec_sdo_request_init_read(&fsm->request, entry);
+        ec_sdo_request_init_read(&fsm->request, fsm->slave,
+                fsm->sync_sdo_index, fsm->sync_subindex);
         fsm->state = ec_fsm_coe_map_state_pdo;
         ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
         ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
         return;
     }
 
-    {
-        ec_sync_t *sync = fsm->slave->sii_syncs + fsm->sync_index;
-
-        if (ec_pdo_mapping_copy(&sync->mapping, &fsm->mapping)) {
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
-        
-        sync->mapping_source = EC_SYNC_MAPPING_COE;
-        ec_pdo_mapping_clear_pdos(&fsm->mapping);
-
-        // next sync manager
-        fsm->sync_index++;
-        ec_fsm_coe_map_action_next_sync(fsm);
-    }
+    // finished reading Pdo mapping/configuration
+    
+    if (ec_pdo_mapping_copy(&fsm->sync->mapping, &fsm->mapping)) {
+        fsm->state = ec_fsm_coe_map_state_error;
+        return;
+    }
+
+    fsm->sync->mapping_source = EC_SYNC_MAPPING_COE;
+    ec_pdo_mapping_clear_pdos(&fsm->mapping);
+
+    // next direction
+    ec_fsm_coe_map_action_next_dir(fsm);
 }
 
 /*****************************************************************************/
@@ -281,58 +274,26 @@
         return;
     }
 
-    {
-        ec_sdo_entry_t *entry;
-
-        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->dir =
-            ec_sync_direction(fsm->slave->sii_syncs + fsm->sync_index);
-
-        if (fsm->slave->master->debug_level)
-            EC_DBG("  Pdo 0x%04X.\n", fsm->pdo->index);
-
-        if (!(fsm->pdo_sdo = ec_slave_get_sdo(fsm->slave, fsm->pdo->index))) {
-            EC_ERR("Slave %u has no Sdo 0x%04X.\n",
-                    fsm->slave->ring_position, fsm->pdo->index);
-            ec_pdo_clear(fsm->pdo);
-            kfree(fsm->pdo);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
-
-        if (ec_pdo_set_name(fsm->pdo, fsm->pdo_sdo->name)) {
-            ec_pdo_clear(fsm->pdo);
-            kfree(fsm->pdo);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
-
-        if (!(entry = ec_sdo_get_entry(fsm->pdo_sdo, 0))) {
-            EC_ERR("Sdo 0x%04X has no subindex 0 on slave %u.\n",
-                    fsm->pdo_sdo->index,
-                    fsm->slave->ring_position);
-            ec_pdo_clear(fsm->pdo);
-            kfree(fsm->pdo);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
-
-        list_add_tail(&fsm->pdo->list, &fsm->mapping.pdos);
-
-        ec_sdo_request_init_read(&fsm->request, entry);
-        fsm->state = ec_fsm_coe_map_state_pdo_entry_count;
-        ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
-        ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
-        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->dir = ec_sync_direction(fsm->sync);
+
+    if (fsm->slave->master->debug_level)
+        EC_DBG("  Pdo 0x%04X.\n", fsm->pdo->index);
+
+    list_add_tail(&fsm->pdo->list, &fsm->mapping.pdos);
+
+    ec_sdo_request_init_read(&fsm->request, fsm->slave, fsm->pdo->index, 0);
+    fsm->state = ec_fsm_coe_map_state_pdo_entry_count;
+    ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
+    ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
 }
 
 /*****************************************************************************/
@@ -374,19 +335,9 @@
         ec_fsm_coe_map_t *fsm /**< finite state machine */
         )
 {
-    ec_sdo_entry_t *entry;
-
     if (fsm->pdo_subindex <= fsm->pdo_subindices) {
-        if (!(entry = ec_sdo_get_entry(fsm->pdo_sdo,
-                        fsm->pdo_subindex))) {
-            EC_ERR("Sdo 0x%04X has no subindex %u on slave %u.\n",
-                    fsm->pdo_sdo->index, fsm->pdo_subindex,
-                    fsm->slave->ring_position);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
-
-        ec_sdo_request_init_read(&fsm->request, entry);
+        ec_sdo_request_init_read(&fsm->request, fsm->slave,
+                fsm->pdo->index, fsm->pdo_subindex);
         fsm->state = ec_fsm_coe_map_state_pdo_entry;
         ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
         ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
@@ -419,8 +370,6 @@
 
     {
         uint32_t pdo_entry_info;
-        ec_sdo_t *sdo;
-        ec_sdo_entry_t *entry;
         ec_pdo_entry_t *pdo_entry;
 
         pdo_entry_info = EC_READ_U32(fsm->request.data);
@@ -438,49 +387,12 @@
         pdo_entry->bit_length = pdo_entry_info & 0xFF;
 
         if (!pdo_entry->index && !pdo_entry->subindex) {
-            // we have a gap in the Pdo, next Pdo entry
-            if (fsm->slave->master->debug_level) {
-                EC_DBG("    Pdo entry gap: %u bit.\n",
-                        pdo_entry->bit_length);
-            }
-
             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;
             }
-
-            list_add_tail(&pdo_entry->list, &fsm->pdo->entries);
-            fsm->pdo_subindex++;
-            ec_fsm_coe_map_action_next_pdo_entry(fsm);
-            return;
-        }
-
-        if (!(sdo = ec_slave_get_sdo(fsm->slave, pdo_entry->index))) {
-            EC_ERR("Slave %u has no Sdo 0x%04X.\n",
-                    fsm->slave->ring_position, pdo_entry->index);
-            ec_pdo_entry_clear(pdo_entry);
-            kfree(pdo_entry);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
-
-        if (!(entry = ec_sdo_get_entry(sdo, pdo_entry->subindex))) {
-            EC_ERR("Slave %u has no Sdo entry 0x%04X:%u.\n",
-                    fsm->slave->ring_position, pdo_entry->index,
-                    pdo_entry->subindex);
-            ec_pdo_entry_clear(pdo_entry);
-            kfree(pdo_entry);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
-
-        if (ec_pdo_entry_set_name(pdo_entry, entry->description)) {
-            ec_pdo_entry_clear(pdo_entry);
-            kfree(pdo_entry);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
         }
 
         if (fsm->slave->master->debug_level) {
@@ -489,9 +401,8 @@
                     pdo_entry->bit_length);
         }
 
+        // next Pdo entry
         list_add_tail(&pdo_entry->list, &fsm->pdo->entries);
-
-        // next Pdo entry
         fsm->pdo_subindex++;
         ec_fsm_coe_map_action_next_pdo_entry(fsm);
     }
--- a/master/fsm_coe_map.h	Tue Feb 26 13:20:32 2008 +0000
+++ b/master/fsm_coe_map.h	Tue Feb 26 16:58:20 2008 +0000
@@ -61,8 +61,9 @@
     ec_slave_t *slave; /**< EtherCAT slave */
     ec_sdo_request_t request; /**< Sdo request */
 
-    unsigned int sync_index; /**< index of the current sync manager */
-    ec_sdo_t *sync_sdo; /**< pointer to the sync managers mapping Sdo */
+    ec_direction_t dir; /**< 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 */
 
--- a/master/fsm_master.c	Tue Feb 26 13:20:32 2008 +0000
+++ b/master/fsm_master.c	Tue Feb 26 16:58:20 2008 +0000
@@ -60,7 +60,6 @@
 void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *);
 void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *);
 void ec_fsm_master_state_sdodict(ec_fsm_master_t *);
-void ec_fsm_master_state_pdomap(ec_fsm_master_t *);
 void ec_fsm_master_state_sdo_request(ec_fsm_master_t *);
 void ec_fsm_master_state_end(ec_fsm_master_t *);
 void ec_fsm_master_state_error(ec_fsm_master_t *);
@@ -88,7 +87,8 @@
 
     // init sub-state-machines
     ec_fsm_slave_config_init(&fsm->fsm_slave_config, fsm->datagram);
-    ec_fsm_slave_scan_init(&fsm->fsm_slave_scan, fsm->datagram);
+    ec_fsm_slave_scan_init(&fsm->fsm_slave_scan, fsm->datagram,
+            &fsm->fsm_slave_config, &fsm->fsm_coe_map);
     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);
@@ -387,7 +387,7 @@
         request->state = EC_REQUEST_IN_PROGRESS;
         up(&master->sdo_sem);
 
-        slave = request->entry->sdo->slave;
+        slave = request->slave;
         if (slave->current_state == EC_SLAVE_STATE_INIT ||
                 slave->online_state == EC_SLAVE_OFFLINE ||
                 slave->error_flag) {
@@ -526,29 +526,6 @@
             return;
         }
 
-        // check, if slaves have their Pdo mapping to be read.
-        list_for_each_entry(slave, &master->slaves, list) {
-            if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)
-                || slave->pdo_mapping_fetched
-                || !slave->sdo_dictionary_fetched
-                || slave->current_state == EC_SLAVE_STATE_INIT
-                || slave->online_state == EC_SLAVE_OFFLINE) continue;
-
-            if (master->debug_level) {
-                EC_DBG("Fetching Pdo mapping from slave %i via CoE.\n",
-                       slave->ring_position);
-            }
-
-            slave->pdo_mapping_fetched = 1;
-
-            // start fetching Pdo mapping
-            fsm->idle = 0;
-            fsm->state = ec_fsm_master_state_pdomap;
-            ec_fsm_coe_map_start(&fsm->fsm_coe_map, slave);
-            ec_fsm_coe_map_exec(&fsm->fsm_coe_map); // execute immediately
-            return;
-        }
-
         // check for pending EEPROM write operations.
         if (ec_fsm_master_action_process_eeprom(fsm))
             return; // EEPROM write request found
@@ -1039,28 +1016,7 @@
 /*****************************************************************************/
 
 /**
- * Scan the Pdo mapping of a slave.
- */
-
-void ec_fsm_master_state_pdomap(
-        ec_fsm_master_t *fsm /**< master 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_master_state_error;
-        return;
-    }
-
-    // fetching of Pdo mapping finished
-    fsm->state = ec_fsm_master_state_end;
-}
-
-/*****************************************************************************/
-
-/**
-   Master state: Sdo REQUEST.
+   Master state: SDO REQUEST.
 */
 
 void ec_fsm_master_state_sdo_request(ec_fsm_master_t *fsm /**< master state machine */)
--- a/master/fsm_slave_scan.c	Tue Feb 26 13:20:32 2008 +0000
+++ b/master/fsm_slave_scan.c	Tue Feb 26 16:58:20 2008 +0000
@@ -54,19 +54,31 @@
 void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_state_eeprom_size(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_scan_t *);
+void ec_fsm_slave_scan_state_preop(ec_fsm_slave_scan_t *);
+void ec_fsm_slave_scan_state_pdos(ec_fsm_slave_scan_t *);
 
 void ec_fsm_slave_scan_state_end(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_state_error(ec_fsm_slave_scan_t *);
 
+void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *);
+void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *);
+
 /*****************************************************************************/
 
 /** Constructor.
  */
-void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *fsm, /**< slave state machine */
-        ec_datagram_t *datagram /**< datagram structure to use */
+void ec_fsm_slave_scan_init(
+        ec_fsm_slave_scan_t *fsm, /**< Slave scanning state machine. */
+        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.
+                                       */
         )
 {
     fsm->datagram = datagram;
+    fsm->fsm_slave_config = fsm_slave_config;
+    fsm->fsm_coe_map = fsm_coe_map;
 
     // init sub state machines
     ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
@@ -556,7 +568,11 @@
         }
     }
 
-    fsm->state = ec_fsm_slave_scan_state_end;
+    if (slave->sii_mailbox_protocols & EC_MBOX_COE) {
+        ec_fsm_slave_scan_enter_preop(fsm);
+    } else {
+        fsm->state = ec_fsm_slave_scan_state_end;
+    }
     return;
 
 end:
@@ -565,6 +581,82 @@
     fsm->state = ec_fsm_slave_scan_state_error;
 }
 
+/*****************************************************************************/
+
+void ec_fsm_slave_scan_enter_preop(
+        ec_fsm_slave_scan_t *fsm /**< slave state machine */
+        )
+{
+    ec_slave_t *slave = fsm->slave;
+
+    if ((slave->current_state & EC_SLAVE_STATE_MASK) < EC_SLAVE_STATE_PREOP) {
+        if (slave->master->debug_level)
+            EC_DBG("Slave %u is not in the state to do mailbox com, setting"
+                    " to PREOP.\n", slave->ring_position);
+        fsm->state = ec_fsm_slave_scan_state_preop;
+        ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
+        ec_fsm_slave_config_start(fsm->fsm_slave_config, slave);
+        ec_fsm_slave_config_exec(fsm->fsm_slave_config);
+    } else {
+        ec_fsm_slave_scan_enter_pdos(fsm);
+    }
+}
+
+/*****************************************************************************/
+
+/** Slave scan state: PREOP.
+ */
+void ec_fsm_slave_scan_state_preop(
+        ec_fsm_slave_scan_t *fsm /**< slave state machine */
+        )
+{
+    if (ec_fsm_slave_config_exec(fsm->fsm_slave_config))
+        return;
+
+    if (!ec_fsm_slave_config_success(fsm->fsm_slave_config)) {
+        fsm->state = ec_fsm_slave_scan_state_error;
+        return;
+    }
+
+    ec_fsm_slave_scan_enter_pdos(fsm);
+}
+
+/*****************************************************************************/
+
+void ec_fsm_slave_scan_enter_pdos(
+        ec_fsm_slave_scan_t *fsm /**< slave state machine */
+        )
+{
+    ec_slave_t *slave = fsm->slave;
+
+    if (slave->master->debug_level)
+        EC_DBG("Scanning Pdo mapping/configuration 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
+}
+
+/*****************************************************************************/
+
+/** Slave scan state: PDOS.
+ */
+void ec_fsm_slave_scan_state_pdos(
+        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 mapping finished
+    fsm->state = ec_fsm_slave_scan_state_end;
+}
+
 /******************************************************************************
  * Common state functions
  *****************************************************************************/
--- a/master/fsm_slave_scan.h	Tue Feb 26 13:20:32 2008 +0000
+++ b/master/fsm_slave_scan.h	Tue Feb 26 16:58:20 2008 +0000
@@ -49,6 +49,7 @@
 #include "fsm_sii.h"
 #include "fsm_change.h"
 #include "fsm_coe.h"
+#include "fsm_coe_map.h"
 #include "fsm_pdo_mapping.h"
 #include "fsm_pdo_config.h"
 
@@ -63,6 +64,9 @@
 {
     ec_slave_t *slave; /**< Slave the FSM runs on. */
     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. */
     unsigned int retries; /**< Retries on datagram timeout. */
 
     void (*state)(ec_fsm_slave_scan_t *); /**< State function. */
@@ -73,7 +77,8 @@
 
 /*****************************************************************************/
 
-void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *, ec_datagram_t *);
+void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *, ec_datagram_t *,
+        ec_fsm_slave_config_t *, ec_fsm_coe_map_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 *);
--- a/master/slave.c	Tue Feb 26 13:20:32 2008 +0000
+++ b/master/slave.c	Tue Feb 26 16:58:20 2008 +0000
@@ -154,7 +154,6 @@
     INIT_LIST_HEAD(&slave->sdo_dictionary);
 
     slave->sdo_dictionary_fetched = 0;
-    slave->pdo_mapping_fetched = 0;
     slave->jiffies_preop = 0;
 
     for (i = 0; i < 4; i++) {
--- a/master/slave.h	Tue Feb 26 13:20:32 2008 +0000
+++ b/master/slave.h	Tue Feb 26 16:58:20 2008 +0000
@@ -53,6 +53,15 @@
 
 /*****************************************************************************/
 
+/** Slave state mask.
+ *
+ * Apply this mask to a slave state byte to get the slave state without
+ * the error flag.
+ */
+#define EC_SLAVE_STATE_MASK 0x0F
+
+/*****************************************************************************/
+
 /** State of an EtherCAT slave.
  */
 typedef enum {
@@ -156,8 +165,6 @@
     struct list_head sdo_dictionary; /**< Sdo dictionary list */
     uint8_t sdo_dictionary_fetched; /**< dictionary has been fetched */
     unsigned long jiffies_preop; /**< time, the slave went to PREOP */
-
-    uint8_t pdo_mapping_fetched; /**< Pdo mapping has been fetched */
 };
 
 /*****************************************************************************/