master/fsm_coe_map.c
changeset 749 c8f1395f818a
parent 741 aece53f82df3
child 751 41a5c537b76d
--- a/master/fsm_coe_map.c	Thu Sep 20 12:57:28 2007 +0000
+++ b/master/fsm_coe_map.c	Thu Sep 20 12:58:35 2007 +0000
@@ -59,6 +59,8 @@
 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 *);
 
+void ec_fsm_coe_map_clear_pdos(ec_fsm_coe_map_t *);
+
 /*****************************************************************************/
 
 /**
@@ -72,6 +74,7 @@
 {
     fsm->state = NULL;
     fsm->fsm_coe = fsm_coe;
+    INIT_LIST_HEAD(&fsm->pdos);
 }
 
 /*****************************************************************************/
@@ -82,6 +85,26 @@
 
 void ec_fsm_coe_map_clear(ec_fsm_coe_map_t *fsm /**< finite state machine */)
 {
+    ec_fsm_coe_map_clear_pdos(fsm);
+}
+
+/*****************************************************************************/
+
+/**
+ */
+
+void ec_fsm_coe_map_clear_pdos(
+        ec_fsm_coe_map_t *fsm /**< finite state machine */
+        )
+{
+    ec_pdo_t *pdo, *next;
+
+    // free all PDOs
+    list_for_each_entry_safe(pdo, next, &fsm->pdos, list) {
+        list_del(&pdo->list);
+        ec_pdo_clear(pdo);
+        kfree(pdo);
+    }
 }
 
 /*****************************************************************************/
@@ -152,7 +175,7 @@
     ec_slave_t *slave = fsm->slave;
     ec_sdo_entry_t *entry;
 
-    for (; fsm->sync_index < 4; fsm->sync_index++) {
+    for (; fsm->sync_index < slave->sii_sync_count; fsm->sync_index++) {
         if (!(fsm->sync_sdo = ec_slave_get_sdo(slave, 0x1C10 + fsm->sync_index)))
             continue;
 
@@ -160,6 +183,8 @@
             EC_DBG("Reading PDO mapping of sync manager %u of slave %u.\n",
                     fsm->sync_index, slave->ring_position);
 
+        ec_fsm_coe_map_clear_pdos(fsm);
+
         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,
@@ -235,9 +260,21 @@
         return;
     }
 
-    // next sync manager
-    fsm->sync_index++;
-    ec_fsm_coe_map_action_next_sync(fsm);
+    {
+        ec_sync_t *sync = fsm->slave->sii_syncs + fsm->sync_index;
+        ec_pdo_t *pdo;
+
+        // exchange sync manager PDO mapping
+        ec_sync_clear_pdos(sync);
+        list_for_each_entry(pdo, &fsm->pdos, list) {
+            ec_sync_add_pdo(sync, pdo);
+        }
+        ec_fsm_coe_map_clear_pdos(fsm);
+
+        // next sync manager
+        fsm->sync_index++;
+        ec_fsm_coe_map_action_next_sync(fsm);
+    }
 }
 
 /*****************************************************************************/
@@ -259,26 +296,58 @@
     }
 
     {
-        uint16_t pdo_index = EC_READ_U16(fsm->request.data);
         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->type =
+            ec_sync_get_pdo_type(fsm->slave->sii_syncs + fsm->sync_index);
+
         if (fsm->slave->master->debug_level)
-            EC_DBG("  PDO 0x%04X.\n", pdo_index);
-
-        if (!(fsm->pdo_sdo = ec_slave_get_sdo(fsm->slave, pdo_index))) {
+            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, pdo_index);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
+                    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 (fsm->pdo_sdo->name && strlen(fsm->pdo_sdo->name)) {
+            if (!(fsm->pdo->name = (char *)
+                        kmalloc(strlen(fsm->pdo_sdo->name) + 1, GFP_KERNEL))) {
+                EC_ERR("Failed to allocate PDO name.\n");
+                ec_pdo_clear(fsm->pdo);
+                kfree(fsm->pdo);
+                fsm->state = ec_fsm_coe_map_state_error;
+                return;
+            }
+            memcpy(fsm->pdo->name, fsm->pdo_sdo->name,
+                    strlen(fsm->pdo_sdo->name) + 1);
+        } else {
+            fsm->pdo->name = NULL;
         }
 
         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);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
-        }
+            ec_pdo_clear(fsm->pdo);
+            kfree(fsm->pdo);
+            fsm->state = ec_fsm_coe_map_state_error;
+            return;
+        }
+
+        list_add_tail(&fsm->pdo->list, &fsm->pdos);
 
         ec_sdo_request_init_read(&fsm->request, entry);
         fsm->state = ec_fsm_coe_map_state_pdo_entry_count;
@@ -369,24 +438,60 @@
 
     {
         uint32_t pdo_entry_info;
-        uint16_t pdo_entry_index;
         ec_sdo_t *sdo;
+        ec_sdo_entry_t *entry;
+        ec_pdo_entry_t *pdo_entry;
 
         pdo_entry_info = EC_READ_U32(fsm->request.data);
-        pdo_entry_index = pdo_entry_info >> 16;
-
-        if (!(sdo = ec_slave_get_sdo(fsm->slave, pdo_entry_index))) {
+
+        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;
+        }
+
+        pdo_entry->index = pdo_entry_info >> 16;
+        pdo_entry->subindex = (pdo_entry_info >> 8) & 0xFF;
+        pdo_entry->bit_length = pdo_entry_info & 0xFF;
+
+        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);
-            fsm->state = ec_fsm_coe_map_state_error;
-            return;
+                    fsm->slave->ring_position, pdo_entry->index);
+            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);
+            kfree(pdo_entry);
+            fsm->state = ec_fsm_coe_map_state_error;
+            return;
+        }
+
+        if (entry->description && strlen(entry->description)) {
+            if (!(pdo_entry->name = (char *)
+                        kmalloc(strlen(entry->description) + 1, GFP_KERNEL))) {
+                EC_ERR("Failed to allocate PDO entry name.\n");
+                kfree(pdo_entry);
+                fsm->state = ec_fsm_coe_map_state_error;
+                return;
+            }
+            memcpy(pdo_entry->name, entry->description, strlen(entry->description) + 1);
+        } else {
+            pdo_entry->name = NULL;
         }
 
         if (fsm->slave->master->debug_level) {
-            size_t bitsize = pdo_entry_info & 0xFFFF;
             EC_DBG("    PDO entry 0x%04X \"%s\" (%u bit).\n",
-                    pdo_entry_index, sdo->name, bitsize);
-        }
+                    pdo_entry->index, pdo_entry->name ? pdo_entry->name : "???",
+                    pdo_entry->bit_length);
+        }
+
+        list_add_tail(&pdo_entry->list, &fsm->pdo->entries);
 
         // next PDO entry
         fsm->pdo_subindex++;