# HG changeset patch # User Florian Pose # Date 1172850225 0 # Node ID 7b1daa325c5f30f7f1e2a7e741a22494e12094b4 # Parent a82c53d6a5d4524d2f580fc3a8ec95b2963b9f5f Implemented alias reading/writing via sysfs. diff -r a82c53d6a5d4 -r 7b1daa325c5f NEWS --- 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. diff -r a82c53d6a5d4 -r 7b1daa325c5f TODO --- 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. diff -r a82c53d6a5d4 -r 7b1daa325c5f master/fsm_master.c --- 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); diff -r a82c53d6a5d4 -r 7b1daa325c5f master/slave.c --- 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; } /*****************************************************************************/