Store slaves in an array instead of a list.
authorFlorian Pose <fp@igh-essen.com>
Thu, 12 Jun 2008 09:32:25 +0000
changeset 1000 5746fdd1ca2e
parent 999 14307580deb6
child 1001 a8eab75aa8e3
Store slaves in an array instead of a list.
TODO
master/fsm_master.c
master/fsm_slave_scan.c
master/globals.h
master/master.c
master/master.h
master/slave.c
master/slave.h
--- a/TODO	Thu Jun 12 09:19:06 2008 +0000
+++ b/TODO	Thu Jun 12 09:32:25 2008 +0000
@@ -8,7 +8,6 @@
 
 Version 1.4.0:
 
-* Slaves as array.
 * Remove the end state of the master state machine.
 * Supply new ec_master_state_t.
 * Implement ecrt_slave_config_state().
--- a/master/fsm_master.c	Thu Jun 12 09:19:06 2008 +0000
+++ b/master/fsm_master.c	Thu Jun 12 09:32:25 2008 +0000
@@ -241,26 +241,26 @@
                 return;
             }
 
+            if (!(master->slaves = (ec_slave_t *)
+                        kmalloc(sizeof(ec_slave_t) * master->slave_count,
+                            GFP_KERNEL))) {
+                EC_ERR("Failed to allocate slave memory!\n");
+                master->slave_count = 0; // FIXME avoid scanning!
+                master->scan_busy = 0;
+                wake_up_interruptible(&master->scan_queue);
+                fsm->state = ec_fsm_master_state_error;
+                return;
+            }
+
             // init slaves
             for (i = 0; i < master->slave_count; i++) {
-                if (!(slave = (ec_slave_t *)
-                            kmalloc(sizeof(ec_slave_t), GFP_KERNEL))) {
-                    EC_ERR("Failed to allocate slave %u!\n", i);
-                    ec_master_clear_slaves(master);
-                    master->scan_busy = 0;
-                    wake_up_interruptible(&master->scan_queue);
-                    fsm->state = ec_fsm_master_state_error;
-                    return;
-                }
-
+                slave = master->slaves + i;
                 ec_slave_init(slave, master, i, i + 1);
 
                 // do not force reconfiguration in operation mode to avoid
                 // unnecesssary process data interruptions
                 if (master->mode != EC_MASTER_MODE_OPERATION)
                     slave->force_config = 1;
-
-                list_add_tail(&slave->list, &master->slaves);
             }
 
             // broadcast clear all station addresses
@@ -272,15 +272,15 @@
         }
     }
 
-    if (list_empty(&master->slaves)) {
-        fsm->state = ec_fsm_master_state_end;
-    } else {
+    if (master->slave_count) {
         // fetch state from first slave
-        fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
+        fsm->slave = master->slaves;
         ec_datagram_fprd(fsm->datagram, fsm->slave->station_address,
                 0x0130, 2);
         fsm->retries = EC_FSM_RETRIES;
         fsm->state = ec_fsm_master_state_read_state;
+    } else {
+        fsm->state = ec_fsm_master_state_end;
     }
 }
 
@@ -338,12 +338,14 @@
         )
 {
     ec_master_t *master = fsm->master;
+    ec_slave_t *slave;
+    ec_sdo_request_t *req;
     ec_master_sdo_request_t *request;
-    ec_sdo_request_t *req;
-    ec_slave_t *slave;
 
     // search for internal requests to be processed
-    list_for_each_entry(slave, &master->slaves, list) {
+    for (slave = master->slaves;
+            slave < master->slaves + master->slave_count;
+            slave++) {
         if (!slave->config)
             continue;
         list_for_each_entry(req, &slave->config->sdo_requests, list) {
@@ -437,7 +439,9 @@
         return;
 
     // check, if slaves have an Sdo dictionary to read out.
-    list_for_each_entry(slave, &master->slaves, list) {
+    for (slave = master->slaves;
+            slave < master->slaves + master->slave_count;
+            slave++) {
         if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)
                 || slave->sdo_dictionary_fetched
                 || slave->current_state == EC_SLAVE_STATE_INIT
@@ -476,15 +480,14 @@
         )
 {
     ec_master_t *master = fsm->master;
-    ec_slave_t *slave = fsm->slave;
 
     // is there another slave to query?
-    if (slave->list.next != &master->slaves) {
+    fsm->slave++;
+    if (fsm->slave < master->slaves + master->slave_count) {
         // fetch state from next slave
         fsm->idle = 1;
-        fsm->slave = list_entry(slave->list.next, ec_slave_t, list);
-        ec_datagram_fprd(fsm->datagram, fsm->slave->station_address,
-                         0x0130, 2);
+        ec_datagram_fprd(fsm->datagram,
+                fsm->slave->station_address, 0x0130, 2);
         fsm->retries = EC_FSM_RETRIES;
         fsm->state = ec_fsm_master_state_read_state;
         return;
@@ -654,7 +657,7 @@
     EC_INFO("Scanning bus.\n");
 
     // begin scanning of slaves
-    fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
+    fsm->slave = master->slaves;
     fsm->state = ec_fsm_master_state_scan_slave;
     ec_fsm_slave_scan_start(&fsm->fsm_slave_scan, fsm->slave);
     ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
@@ -694,8 +697,8 @@
 #endif
 
     // another slave to fetch?
-    if (slave->list.next != &master->slaves) {
-        fsm->slave = list_entry(slave->list.next, ec_slave_t, list);
+    fsm->slave++;
+    if (slave < master->slaves + master->slave_count) {
         ec_fsm_slave_scan_start(&fsm->fsm_slave_scan, fsm->slave);
         ec_fsm_slave_scan_exec(&fsm->fsm_slave_scan); // execute immediately
         return;
--- a/master/fsm_slave_scan.c	Thu Jun 12 09:19:06 2008 +0000
+++ b/master/fsm_slave_scan.c	Thu Jun 12 09:32:25 2008 +0000
@@ -338,10 +338,10 @@
     }
 
     dl_status = EC_READ_U16(datagram->data);
-    for (i = 0; i < 4; i++) {
-        slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
-        slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
-        slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
+    for (i = 0; i < EC_SLAVE_MAX_PORTS; i++) {
+        slave->ports[i].dl_link = dl_status & (1 << (4 + i)) ? 1 : 0;
+        slave->ports[i].dl_loop = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
+        slave->ports[i].dl_signal = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
     }
 
     // Start fetching SII size
--- a/master/globals.h	Thu Jun 12 09:19:06 2008 +0000
+++ b/master/globals.h	Thu Jun 12 09:32:25 2008 +0000
@@ -99,6 +99,9 @@
 /** Size of an FMMU configuration page. */
 #define EC_FMMU_PAGE_SIZE 16
 
+/** Maximum number of slave ports. */
+#define EC_SLAVE_MAX_PORTS 4
+
 /** Slave state mask.
  *
  * Apply this mask to a slave state byte to get the slave state without
--- a/master/master.c	Thu Jun 12 09:19:06 2008 +0000
+++ b/master/master.c	Thu Jun 12 09:32:25 2008 +0000
@@ -92,7 +92,7 @@
     master->injection_seq_fsm = 0;
     master->injection_seq_rt = 0;
 
-    INIT_LIST_HEAD(&master->slaves);
+    master->slaves = NULL;
     master->slave_count = 0;
     
     INIT_LIST_HEAD(&master->configs);
@@ -245,15 +245,20 @@
  */
 void ec_master_clear_slaves(ec_master_t *master)
 {
-    ec_slave_t *slave, *next;
-
-    list_for_each_entry_safe(slave, next, &master->slaves, list) {
-        list_del(&slave->list);
+    ec_slave_t *slave;
+
+    for (slave = master->slaves;
+            slave < master->slaves + master->slave_count;
+            slave++) {
         ec_slave_clear(slave);
         kfree(slave);
     }
 
-    master->slave_count = 0;
+    if (master->slave_count) {
+        kfree(master->slaves);
+        master->slaves = NULL;
+        master->slave_count = 0;
+    }
 }
 
 /*****************************************************************************/
@@ -413,7 +418,9 @@
     }
 
     // set states for all slaves
-    list_for_each_entry(slave, &master->slaves, list) {
+    for (slave = master->slaves;
+            slave < master->slaves + master->slave_count;
+            slave++) {
         ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
     }
 #ifdef EC_EOE
@@ -466,7 +473,9 @@
     ec_master_clear_slave_configs(master);
 
     // set states for all slaves
-    list_for_each_entry(slave, &master->slaves, list) {
+    for (slave = master->slaves;
+            slave < master->slaves + master->slave_count;
+            slave++) {
         ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
     }
 #ifdef EC_EOE
@@ -1013,23 +1022,25 @@
         uint16_t position /**< Slave position. */
         )
 {
-    ec_slave_t *slave;
-    unsigned int alias_found = 0, relative_position = 0;
-
-	list_for_each_entry(slave, &master->slaves, list) {
-        if (!alias_found) {
-			if (alias && slave->sii.alias != alias)
+    ec_slave_t *slave = master->slaves;
+
+    if (alias) {
+        // find slave with the given alias
+        for (; slave < master->slaves + master->slave_count;
+                slave++) {
+			if (slave->sii.alias != alias)
 				continue;
-			alias_found = 1;
-			relative_position = 0;
 		}
-		if (relative_position == position) {
-            return slave;
-        }
-		relative_position++;
+        if (slave == master->slaves + master->slave_count)
+            return NULL;
 	}
 
-    return NULL;
+    slave += position;
+    if (slave < master->slaves + master->slave_count) {
+        return slave;
+    } else {
+        return NULL;
+    }
 }
 
 /*****************************************************************************/
--- a/master/master.h	Thu Jun 12 09:19:06 2008 +0000
+++ b/master/master.h	Thu Jun 12 09:32:25 2008 +0000
@@ -99,8 +99,8 @@
     unsigned int injection_seq_rt; /**< datagram injection sequence number
                                      for the realtime side */
 
-    struct list_head slaves; /**< list of slaves on the bus */
-    unsigned int slave_count; /**< number of slaves on the bus */
+    ec_slave_t *slaves; /**< Array of slaves on the bus. */
+    unsigned int slave_count; /**< Number of slaves on the bus. */
 
     struct list_head configs; /**< Bus configuration list. */
     unsigned int configs_attached; /**< Slave configurations were attached. */
--- a/master/slave.c	Thu Jun 12 09:19:06 2008 +0000
+++ b/master/slave.c	Thu Jun 12 09:32:25 2008 +0000
@@ -72,11 +72,10 @@
 {
     unsigned int i;
 
+    slave->master = master;
     slave->ring_position = ring_position;
     slave->station_address = station_address;
 
-    slave->master = master;
-
     slave->config = NULL;
     slave->requested_state = EC_SLAVE_STATE_PREOP;
     slave->current_state = EC_SLAVE_STATE_UNKNOWN;
@@ -88,6 +87,13 @@
     slave->base_build = 0;
     slave->base_fmmu_count = 0;
 
+    for (i = 0; i < EC_SLAVE_MAX_PORTS; i++) {
+        slave->ports[i].dl_link = 0;
+        slave->ports[i].dl_loop = 0;
+        slave->ports[i].dl_signal = 0;
+        slave->sii.physical_layer[i] = 0xFF;
+    }
+
     slave->sii_words = NULL;
     slave->sii_nwords = 0;
 
@@ -123,13 +129,6 @@
 
     slave->sdo_dictionary_fetched = 0;
     slave->jiffies_preop = 0;
-
-    for (i = 0; i < 4; i++) {
-        slave->dl_link[i] = 0;
-        slave->dl_loop[i] = 0;
-        slave->dl_signal[i] = 0;
-        slave->sii.physical_layer[i] = 0xFF;
-    }
 }
 
 /*****************************************************************************/
--- a/master/slave.h	Thu Jun 12 09:19:06 2008 +0000
+++ b/master/slave.h	Thu Jun 12 09:32:25 2008 +0000
@@ -71,39 +71,48 @@
 
     // Strings
     char **strings; /**< Strings in SII categories. */
-    unsigned int string_count; /**< number of SII strings */
+    unsigned int string_count; /**< Number of SII strings. */
 
     // General
     unsigned int has_general; /**< General category present. */
-    char *group; /**< slave group acc. to SII */
-    char *image; /**< slave image name acc. to SII */
-    char *order; /**< slave order number acc. to SII */
-    char *name; /**< slave name acc. to SII */
-    uint8_t physical_layer[4]; /**< port media */
+    char *group; /**< Group name. */
+    char *image; /**< Image name. */
+    char *order; /**< Order number. */
+    char *name; /**< Slave name. */
+    uint8_t physical_layer[EC_SLAVE_MAX_PORTS]; /**< Port media. */
     ec_sii_coe_details_t coe_details; /**< CoE detail flags. */
     ec_sii_general_flags_t general_flags; /**< General flags. */
-    int16_t current_on_ebus; /**< power consumption */
+    int16_t current_on_ebus; /**< Power consumption in mA. */
 
     // SyncM
-    ec_sync_t *syncs; /**< SII SYNC MANAGER categories */
-    unsigned int sync_count; /**< number of sync managers in SII */
+    ec_sync_t *syncs; /**< SYNC MANAGER categories. */
+    unsigned int sync_count; /**< Number of sync managers. */
 
     // [RT]XPDO
-    struct list_head pdos; /**< SII [RT]XPDO categories */
+    struct list_head pdos; /**< SII [RT]XPDO categories. */
 } ec_sii_t;
 
 /*****************************************************************************/
 
+/** EtherCAT slave port information.
+ */
+typedef struct {
+    uint8_t dl_link; /**< Link detected. */
+    uint8_t dl_loop; /**< Loop closed. */
+    uint8_t dl_signal; /**< Detected signal on RX port. */
+} ec_slave_port_t;
+
+/*****************************************************************************/
+
 /** EtherCAT slave.
  */
 struct ec_slave
 {
-    struct list_head list; /**< list item */
-    ec_master_t *master; /**< master owning the slave */
+    ec_master_t *master; /**< Master owning the slave. */
 
     // addresses
-    uint16_t ring_position; /**< ring position */
-    uint16_t station_address; /**< configured station address */
+    uint16_t ring_position; /**< Ring position. */
+    uint16_t station_address; /**< Configured station address. */
 
     // configuration
     ec_slave_config_t *config; /**< Current configuration. */
@@ -113,26 +122,24 @@
     unsigned int force_config; /**< Force (re-)configuration. */
 
     // base data
-    uint8_t base_type; /**< slave type */
-    uint8_t base_revision; /**< revision */
-    uint16_t base_build; /**< build number */
-    uint16_t base_fmmu_count; /**< number of supported FMMUs */
+    uint8_t base_type; /**< Slave type. */
+    uint8_t base_revision; /**< Revision. */
+    uint16_t base_build; /**< Build number. */
+    uint16_t base_fmmu_count; /**< Number of supported FMMUs. */
 
     // data link status
-    uint8_t dl_link[4]; /**< link detected */
-    uint8_t dl_loop[4]; /**< loop closed */
-    uint8_t dl_signal[4]; /**< detected signal on RX port */
+    ec_slave_port_t ports[EC_SLAVE_MAX_PORTS];
 
     // SII
     uint16_t *sii_words; /**< Complete SII image. */
     size_t sii_nwords; /**< Size of the SII contents in words. */
 
-    // slave information interface
-    ec_sii_t sii; /**< SII data. */
+    // Slave information interface
+    ec_sii_t sii; /**< Extracted SII data. */
 
     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 sdo_dictionary_fetched; /**< Dictionary has been fetched. */
+    unsigned long jiffies_preop; /**< Time, the slave went to PREOP. */
 };
 
 /*****************************************************************************/