Implemented alias reading/writing via sysfs.
authorFlorian Pose <fp@igh-essen.com>
Fri, 02 Mar 2007 15:43:45 +0000
changeset 607 7b1daa325c5f
parent 606 a82c53d6a5d4
child 608 029d70ceaaf1
Implemented alias reading/writing via sysfs.
NEWS
TODO
master/fsm_master.c
master/slave.c
--- a/NEWS	Fri Mar 02 14:47:09 2007 +0000
+++ b/NEWS	Fri Mar 02 15:43:45 2007 +0000
@@ -21,6 +21,7 @@
     devices to the master, which decides, which ones to register.
 * All EEPROM write operations from user space are now blocking until
   completion and returning appropriate error codes.
+* Implemented setting of secondary slave address (alias) via sysfs.
 * Removed annoying eeprom_write_enable file. EEPROM writing always enabled.
 * Removed EtherCAT line comments from 8139too drivers.
 
--- a/TODO	Fri Mar 02 14:47:09 2007 +0000
+++ b/TODO	Fri Mar 02 15:43:45 2007 +0000
@@ -16,6 +16,7 @@
   - SDO dictionary and -access in operation mode.
   - SDO write access in sysfs.
   - Speed up IDLE-FSM through fast mode with schedule().
+  - Evaluate EEPROM contents after writing.
 
 * Future features:
   - Distributed clocks.
--- a/master/fsm_master.c	Fri Mar 02 14:47:09 2007 +0000
+++ b/master/fsm_master.c	Fri Mar 02 15:43:45 2007 +0000
@@ -311,7 +311,9 @@
         }
 
         // found pending EEPROM write operation. execute it!
-        EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position);
+        if (master->debug_level)
+            EC_DBG("Writing EEPROM data to slave %i...\n",
+                    slave->ring_position);
         fsm->eeprom_request = request;
         fsm->eeprom_index = 0;
         ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
@@ -782,7 +784,8 @@
    Master state: WRITE EEPROM.
 */
 
-void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *fsm /**< master state machine */)
+void ec_fsm_master_state_write_eeprom(
+        ec_fsm_master_t *fsm /**< master state machine */)
 {
     ec_master_t *master = fsm->master;
     ec_eeprom_write_request_t *request = fsm->eeprom_request;
@@ -792,8 +795,8 @@
 
     if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
         slave->error_flag = 1;
-        EC_ERR("Failed to write EEPROM contents to slave %i.\n",
-               slave->ring_position);
+        EC_ERR("Failed to write EEPROM data to slave %i.\n",
+                slave->ring_position);
         request->state = EC_EEPROM_REQ_ERROR;
         wake_up(&master->eeprom_queue);
         fsm->state = ec_fsm_master_state_error;
@@ -811,7 +814,9 @@
     }
 
     // finished writing EEPROM
-    EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position);
+    if (master->debug_level)
+        EC_DBG("Finished writing EEPROM data to slave %i.\n",
+                slave->ring_position);
     request->state = EC_EEPROM_REQ_COMPLETED;
     wake_up(&master->eeprom_queue);
 
--- a/master/slave.c	Fri Mar 02 14:47:09 2007 +0000
+++ b/master/slave.c	Fri Mar 02 15:43:45 2007 +0000
@@ -65,11 +65,13 @@
 EC_SYSFS_READ_ATTR(info);
 EC_SYSFS_READ_WRITE_ATTR(state);
 EC_SYSFS_READ_WRITE_ATTR(eeprom);
+EC_SYSFS_READ_WRITE_ATTR(alias);
 
 static struct attribute *def_attrs[] = {
     &attr_info,
     &attr_state,
     &attr_eeprom,
+    &attr_alias,
     NULL,
 };
 
@@ -773,19 +775,57 @@
 /*****************************************************************************/
 
 /**
-   Schedules an EEPROM write operation.
-   \return 0 in case of success, else < 0
-*/
+ * Schedules an EEPROM write request.
+ * \return 0 case of success, otherwise error code.
+ */
+
+int ec_slave_schedule_eeprom_writing(ec_eeprom_write_request_t *request)
+{
+    ec_master_t *master = request->slave->master;
+
+    request->state = EC_EEPROM_REQ_QUEUED;
+
+    // schedule EEPROM write request.
+    down(&master->eeprom_sem);
+    list_add_tail(&request->list, &master->eeprom_requests);
+    up(&master->eeprom_sem);
+
+    // wait for processing through FSM
+    if (wait_event_interruptible(master->eeprom_queue,
+                request->state != EC_EEPROM_REQ_QUEUED)) {
+        // interrupted by signal
+        down(&master->eeprom_sem);
+        if (request->state == EC_EEPROM_REQ_QUEUED) {
+            list_del(&request->list);
+            up(&master->eeprom_sem);
+            return -EINTR;
+        }
+        // request already processing: interrupt not possible.
+        up(&master->eeprom_sem);
+    }
+
+    // wait until master FSM has finished processing
+    wait_event(master->eeprom_queue, request->state != EC_EEPROM_REQ_BUSY);
+
+    return request->state == EC_EEPROM_REQ_COMPLETED ? 0 : -EIO;
+}
+
+/*****************************************************************************/
+
+/**
+ * Writes complete EEPROM contents to a slave.
+ * \return data size written in case of success, otherwise error code.
+ */
 
 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
-                              const uint8_t *data, /**< new EEPROM data */
-                              size_t size /**< size of data in bytes */
-                              )
+        const uint8_t *data, /**< new EEPROM data */
+        size_t size /**< size of data in bytes */
+        )
 {
     ec_eeprom_write_request_t request;
     const uint16_t *cat_header;
     uint16_t cat_type, cat_size;
-    ec_master_t *master = slave->master;
+    int ret;
 
     if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
         EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
@@ -803,7 +843,6 @@
     request.words = (const uint16_t *) data;
     request.offset = 0;
     request.size = size / 2;
-    request.state = EC_EEPROM_REQ_QUEUED;
 
     if (request.size < 0x0041) {
         EC_ERR("EEPROM data too short! Dropping.\n");
@@ -826,30 +865,59 @@
         cat_type = EC_READ_U16(cat_header);
     }
 
-    // data ok: schedule EEPROM write request.
-    down(&master->eeprom_sem);
-    list_add_tail(&request.list, &master->eeprom_requests);
-    up(&master->eeprom_sem);
-
-    // wait for processing through FSM
-    if (wait_event_interruptible(master->eeprom_queue,
-                request.state != EC_EEPROM_REQ_QUEUED)) {
-        // interrupted by signal
-        down(&master->eeprom_sem);
-        if (request.state == EC_EEPROM_REQ_QUEUED) {
-            list_del(&request.list);
-            up(&master->eeprom_sem);
-            return -EINTR;
-        }
-        // request already processing: interrupt not possible.
-        up(&master->eeprom_sem);
-    }
-
-    // wait until master FSM has finished processing
-    wait_event(master->eeprom_queue, request.state != EC_EEPROM_REQ_BUSY);
-
-    return request.state == EC_EEPROM_REQ_COMPLETED ? size : -EIO;
-}
+    // EEPROM data ok. schedule writing.
+    if ((ret = ec_slave_schedule_eeprom_writing(&request)))
+        return ret; // error code
+
+    return size; // success
+}
+
+/*****************************************************************************/
+
+/**
+ * Writes the Secondary slave address (alias) to the slave's EEPROM.
+ * \return data size written in case of success, otherwise error code.
+ */
+
+ssize_t ec_slave_write_alias(ec_slave_t *slave, /**< EtherCAT slave */
+        const uint8_t *data, /**< alias string */
+        size_t size /**< size of data in bytes */
+        )
+{
+    ec_eeprom_write_request_t request;
+    char *remainder;
+    uint16_t alias, word;
+    int ret;
+
+    if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
+        EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
+        return -EBUSY;
+    }
+
+    alias = simple_strtoul(data, &remainder, 0);
+    if (remainder == (char *) data || (*remainder && *remainder != '\n')) {
+        EC_ERR("Invalid alias value! Dropping.\n");
+        return -EINVAL;
+    }
+    
+    // correct endianess
+    EC_WRITE_U16(&word, alias);
+
+    // init EEPROM write request
+    INIT_LIST_HEAD(&request.list);
+    request.slave = slave;
+    request.words = &word;
+    request.offset = 0x0004;
+    request.size = 1;
+
+    if ((ret = ec_slave_schedule_eeprom_writing(&request)))
+        return ret; // error code
+
+    slave->sii_alias = alias; // FIXME: do this in state machine
+
+    return size; // success
+}
+
 
 /*****************************************************************************/
 
@@ -895,6 +963,9 @@
             }
         }
     }
+    else if (attr == &attr_alias) {
+        return sprintf(buffer, "%u\n", slave->sii_alias);
+    }
 
     return 0;
 }
@@ -937,8 +1008,11 @@
     else if (attr == &attr_eeprom) {
         return ec_slave_write_eeprom(slave, buffer, size);
     }
-
-    return -EINVAL;
+    else if (attr == &attr_alias) {
+        return ec_slave_write_alias(slave, buffer, size);
+    }
+
+    return -EIO;
 }
 
 /*****************************************************************************/