From d8d30c4a1fc159d7a597cb2cd4558a22c5f815a1 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Fri, 2 Mar 2007 15:43:45 +0000 Subject: [PATCH] Implemented alias reading/writing via sysfs. --- NEWS | 1 + TODO | 1 + master/fsm_master.c | 15 +++-- master/slave.c | 130 ++++++++++++++++++++++++++++++++++---------- 4 files changed, 114 insertions(+), 33 deletions(-) diff --git a/NEWS b/NEWS index df33132a..9230d444 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,7 @@ Changes in version 1.3.0: 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. diff --git a/TODO b/TODO index df373b69..5e50954b 100644 --- a/TODO +++ b/TODO @@ -16,6 +16,7 @@ $Id$ - 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. diff --git a/master/fsm_master.c b/master/fsm_master.c index b0525b7a..4f9104bb 100644 --- a/master/fsm_master.c +++ b/master/fsm_master.c @@ -311,7 +311,9 @@ int ec_fsm_master_action_process_eeprom( } // 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 @@ void ec_fsm_master_state_configure_slave(ec_fsm_master_t *fsm 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 @@ void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *fsm /**< master state mac 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 @@ void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *fsm /**< master state mac } // 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); diff --git a/master/slave.c b/master/slave.c index 44fbfb90..5b9a590f 100644 --- a/master/slave.c +++ b/master/slave.c @@ -65,11 +65,13 @@ ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *, 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 @@ size_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */ /*****************************************************************************/ /** - 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 @@ ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */ 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,31 +865,60 @@ ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */ 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); + // EEPROM data ok. schedule writing. + if ((ret = ec_slave_schedule_eeprom_writing(&request))) + return ret; // error code - // 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); + 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; } - // wait until master FSM has finished processing - wait_event(master->eeprom_queue, request.state != EC_EEPROM_REQ_BUSY); + 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); - return request.state == EC_EEPROM_REQ_COMPLETED ? size : -EIO; + // 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 @@ ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */ } } } + else if (attr == &attr_alias) { + return sprintf(buffer, "%u\n", slave->sii_alias); + } return 0; } @@ -937,8 +1008,11 @@ ssize_t ec_store_slave_attribute(struct kobject *kobj, /**< slave's kobject */ else if (attr == &attr_eeprom) { return ec_slave_write_eeprom(slave, buffer, size); } + else if (attr == &attr_alias) { + return ec_slave_write_alias(slave, buffer, size); + } - return -EINVAL; + return -EIO; } /*****************************************************************************/