master/slave.c
changeset 607 7b1daa325c5f
parent 606 a82c53d6a5d4
child 609 611d738a1392
--- 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;
 }
 
 /*****************************************************************************/